React의 컴포넌트는 props라는 것을 입력받을 수 있고, React 엘리먼트를 반환한다. 오늘은 이 props에 대해 알아보자.
React 엘리먼트는 그냥 HTML 마크업일 수도 있고 사용자 정의 컴포넌트일 수도 있다. 만일 사용자 정의 컴포넌트라면, React는 해당 JSX의 attribute들을 props라는 이름의 단일 객체안에 넣어 컴포넌트에 전달한다. 아래의 코드를 살펴보자.
const Title = <h1>post title</h1>; // 일반 HTML 마크업
const Body = <PostBody content="post content" /> // 사용자가 정의한 컴포넌트
const PostBody = (props) => {
return (
<p>post body: ${props.content}</p> // post body: post content
);
};
PostBody라는 컴포넌트를 불러올 때 content라는 이름의 attribute를 더해주었고, 컴포넌트는 인자로 props 객체를 받아와서 props.content를 사용하고 있다.
결론부터 말하자면 props는 재사용성을 높이기 위해 사용된다.
예를 들어 반복되는 디자인에 다른 내용을 가진 UI가 있다면 props가 용이하게 쓰일 수 있을 것이다. 아래의 코드를 보자.
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
App 컴포넌트 안에서 Welcome 컴포넌트가 여러번 호출되고 있다. 하지만 각 호출마다 name prop이 다르게 전달되고 있어 그 내용이 제각각 다르다. 이 예시코드에서는 단지 내용이 다른 h1태그를 여러개 만들어내는 것 뿐이지만, 앱의 내용이 더 커지면 props의 편리함이 배가된다.
쇼핑몰의 상품 리스트를 화면에 나타내는 앱을 만든다고 생각해보자. 상품 리스트 데이터에 map함수를 사용하여 map함수 내부에 상품 아이템의 UI 로직을 전부 넣어야 할 것이다. 하지만 props를 사용한다면 상품 아이템 컴포넌트를 따로 만들고, map 함수 내부에서는 <ProductItem productData={productData} />
와 같이 props를 넘겨주기만 하고 나머지 UI 구성은 ProductItem 컴포넌트에서 하면 될 것이다.
이와 같이 자주 사용되는 비슷한 UI들의 공통되는 부분을 모아 컴포넌트를 만들어서 디테일한 부분은 props로 수정할 수 있게끔 로직을 구성해두면 개발을 하는 데에 있어 더욱 편리할 것이다.
컴포넌트는 자신의 props를 변경할 수 없다.
function Welcome(props) {
props.name = Kane; // 오류 발생
return <h1>Hello, {props.name}</h1>;
}
function App() {
return <Welcome name="Sara" />;
}
다음과 같이 받아온 props를 변경하려고 하면 오류가 발생한다. 물론 부모 컴포넌트에서 props를 변경하는 함수도 같이 props로 넘겨준다면 자식 컴포넌트에서 함수를 실행하는 것으로 props를 변경할 수는 있겠으나, 이는 React의 의도에 어긋나는 것이며 권장되지 않는다.
Props와 State의 공통점은 그 값이 바뀌면 소유한 컴포넌트가 리렌더링 된다는 것이다. 차이점은 Props는 부모 컴포넌트로 부터 받으며 자신이 그 값을 바꿀 수 없고, State는 자기 자신이 소유하며 값을 바꿀 수 있다는 것이다.
그렇다면 어떤 때에 prop을 사용하고 어떤 때에 state을 사용해야 할까? 잠시 Hooks가 등장하기 이전으로 돌아가보자.
Hooks가 등장하기 이전에는 함수형 컴포넌트에서 State를 사용할 수 없었다. 그래서 State나 Life Cycle을 사용하지 못 하는 함수형 컴포넌트를 Dumb Component라고 불렀고, 클래스형 컴포넌트를 Smart Component라고 불렀다. 그래서 단독적인 리렌더링이 필요하지 않은 컴포넌트는 Dumb Component로, 필요하다면 Smart Component로 분류하여 사용하였다.
지금에 와서는 함수형 컴포넌트도 State를 사용할 수 있게 되어서 어느 컴포넌트에서 State를 사용해야하는지 꽤 어렵다. 그래서 고안된 디자인 패턴이 presentation/container이다.(리액트를 다루는 기술에서는 component/container라고 되어있다.) 이것은 Redux의 개발자중 한 명인 Dan abramov이 권장하고 있는 디자인 패턴이다.
container는 서버와 통신하거나 Redux 스토어로부터 데이터를 받아오고 데이터를 가공/관리하는 등의 작업을 하여 presentation에게 필요한 데이터와 데이터를 조작하는 함수 등을 props로 전달하면 presentation은 props로 받아온 데이터를 DOM과 style으로 화면에 표시한다.
대부분의 상황에서 presentation은 State를 가지지 않으며 만약 가진다면 UI에 관한 State를 가지게 된다.
이렇게 컴포넌트를 분리하게 되면 관심사가 잘 분리되며 코드의 재사용성이 높아진다. 무엇보다 코드를 읽기 쉬워지게 된다.
물론 이것은 엄격한 규칙이 아니라 하나의 방법론이기 때문에 반드시 지켜야 하는 것은 아니며, presentation과 container를 구분하기 어려운 경우에 일부러 나눌 필요는 없다는 모양이다.
오늘은 React의 Props에 대해 알아보았다. 포스팅을 하며 React 디자인 패턴으로까지 이야기가 흘러갔는데, 어렴풋이 알던 개념을 자세히 알게 되는 과정이 꽤 즐겁다.
다음은 Redux에 대해 포스팅 할 계획이다.