컴포넌트를 사용하는 것 여러 이점 중 하나는 바로 재사용이 가능하다는 점입니다. 만약 페이지에 내용은 다르지만 같은 구조와 기능을 가진 것을 여러 번 표시해야한다면 컴포넌트를 사용하는 것이 하나의 해결책이 됩니다. 실제로는 단 한 번만 사용하는 컴포넌트를 만들 때도 많지만, 이론적으로 컴포넌트들은 얼마든지 재사용이 가능합니다. 매개 변수(Parameter)를 받아 같은 계산을 실행하는 함수처럼 컴포넌트는 데이터를 받아 같은 과정을 거쳐 결과를 보여줍니다. 여기서 우리가 넘겨주는 데이터가 바로 Prop(Property, 속성)입니다.

Prop

Prop은 '속성'이라는 의미를 가지며 데이터를 컴포넌트로 전달하고 그 컴포넌트에서 받은 데이터를 사용할 수 있게 합니다. 컴포넌트를 여러 번 재사용하기 위해 속성을 사용하는 것이 일차적 목표이나, 컴포넌트를 사용할 때 해당 컴포넌트에 필요한 데이터를 전달하려는 성격을 가지고 있기 때문에 꼭 여러 번 재사용하기 위해 속성을 사용하는 것은 아닙니다. 그보다 중요한 건 만들어진 컴포넌트에 데이터를 전달해 준다는 사실입니다. 그렇다면 속성은 어떻게 전달할까요?

Prop 사용해보기

import Receive from "./Receive";

const Send = () => {
  const secondData = "second props data";
  return (
    <>
      <Receive propsName1="first props data" propsName2={secondData} />
    </>
  );
};

export default Send;

위의 코드에서 컴포넌트 내부의 propsName1='first props data' propsName2='second props data'는 각각의 이름으로 속성을 전달하는 것입니다. 속성의 이름은 개발자가 마음대로 정할 수 있습니다. 중괄호({})는 JSX에서 자바스크립트 문법을 사용하는 방법이며, 중괄호 안에 자바스크립트 코드를 작성할 수 있습니다. 만약 평가된 자바스트립트의 값이 falsy한 값이 아니라면 해당 값은 화면에 렌더링 됩니다.

const receive = (props) => {
  return <>
    <p>propsName1: {props.propsName1}</p>
    <p>propsName1: {props.propsName1}</p>
  </>
}

export default receive;

위의 코드는 전달받은 속성을 사용하는 방법의 예시 입니다. 모든 컴포넌트는 렌더링될 때 인자로 속성을 전달받습니다. 전달받은 속성을 사용하기 위해 props라는 매개 변수(이름은 마음대로 설정 가능하지만 일반적으로 props를 사용합니다.)를 만들어 속성에 접근할 수 있게 만들어줍니다. 그러면 해당 매개 변수에 전달 받은 모든 속성이 키-값 쌍으로 들어있는 객체가 할당됩니다. 이제 이 객체를 활용하여 전달받은 데이터에 자유롭게 접근하여 데이터를 읽을 수 있습니다.

props 주의 사항

속성은 읽기 전용(read-only)입니다.

컴포넌트가 전달받은 속성을 수정해서는 안 되며, 속성은 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하는 데 사용되어야 함을 의미합니다. 컴포넌트 내에서 직접적으로 속성을 수정하려고 시도하면 오류가 발생합니다. 단 속성을 전달하는 컴포넌트인 부모 컴포넌트에서 전달하는 속성의 내용이 바뀌면 속성을 전달 받는 컴포넌트는 다시 렌더링되면서 바뀐 값을 사용합니다.

Prop drilling

출처: React 공식문서,&nbsp; Context를 사용해 데이터를 깊게 전달하기

어떤 속성을 트리를 통해 깊이 전해줘야 하거나, 많은 컴포넌트에서 같은 속성이 필요한 경우에 코드가 장황해지고 불편할 수 있습니다. 그럴때는 속성을 전달하여 사용하기보다는 React에 기본 내장된 Context API를 사용하거나, Redux, Recoil, zustand 등의 상태관리 라이브러리를 사용하는 것이 더 바람직합니다.

더 다양한 문법

구조분해 할당

구조분해할당을 통해 더 간편하게 속성을 전달할 수 있습니다.

const book = {
  title: '제목',
  description: '책 설명',
  price: 10000,
}

위와 같은 객체가 이미 존재할 때,

<Receive
  title={book.title}
  description={book.description}  
  image={book.price} />

// 구조분해 할당 이용하기
<Receive
  {...book} />

그리고 데이터를 전달 받는 컴포넌트에서도 구조분해 할당을 통해 데이터를 받을 수 있습니다. 컴포넌트인것을 더 쉽게 파악하기 위해 export문을 사용하고 화살표 함수형태가 아닌 function 키워드 이용한 선언문으로 작성하였습니다.

export default function receive(props) {}

// 구조분해 할당 이용하기
export default function receive({title, description, price}) {}

객체로 만들어 Prop 전달하기

자바스크립트 객체로 이미 구성된 데이터가 있다면 하나의 속성 값으로 전달할 수 있습니다.

<Receive book={book} />

// prop 받기
export default function receive({ book }) {}

기본 Prop 값

결국 Prop이라는 객체가 매개 변수로 들어오는 함수이기 때문에 객체 비구조화를 통해 기본 값을 지정할 수 있습니다.

export default function receive({title, description, price = 8000}) {}

children Prop

리액트에서는 컴포넌트의 열는 태그 닫는 태그 사이에 들어간 내용은 곧 바로 렌더링되지 않습니다. 대신 해당 내용들은 자동으로 그 내용을 감싸는 컴포넌트에 속성으로 전달됩니다. 이를 사용하기 위해 리액트의 모든 컴포는트는 특별한 종류의 속성인 children 속성을 가지고 있습니다. children은 개발자가 직접 정의하지 않는 속성으로 JSX코드 상에서 컴포넌트의 열는 태그와 닫는 태그 사이에 있는 모든 내용이 들어갑니다.

const Send = () => {
  return
    <Receive>안녕하세요</Receive>
};

// children으로 태그 사이의 내용 전달받기
export default function receive({children}) {
  return <>
    <p>{children}</p>
  </>
}

이 children을 통해 리액트는 구성 요소가 더욱 유연해지고 임의의 콘텐츠를 수용할 수 있게 됩니다.

참고자료

React, [컴포넌트에 props 전달하기,Props 전달하기의 문제점]

+ Recent posts