[React] Props란? Props Drilling과 해결 방법
📑 개요
Props란?
부모 컴포넌트가 자식 컴포넌트로 데이터를 전달할 때 사용되며 읽기 전용(immutable)이기 때문에 컴포넌트 내에서 변경할 수 없다.
// 부모 컴포넌트에서 자식 컴포넌트로 props 전달
function ParentComponent() {
return <ChildComponent name="ChaCha" />;
}
// 자식 컴포넌트에서 props 사용
function ChildComponent(props) {
return <p>Hello, {props.name}!</p>;
}
- State와의 차이
State는 컴포넌트 자기 자신이 갖고 있는 값으로 setState()를 사용하여 변경할 수 있다.
Props | State | |
불변성 | 읽기 전용(immutabla) | 컴포넌트 내부에서 관리되는 상태로 변경시 setState() 사용 |
소유권 | 해당 컴포넌트에서 소유하지 않음. 부모 컴포너트에서 자식 컴포넌트로 전달되는 데이터. |
컴포넌트 자체가 관리하고 있는 내부 상태. 컴포넌트가 렌더링 되는 동안 유지되며 해당 컴포넌트에서만 사용됨. |
변경 가능성 | X | O |
Props Drilling이란?
props를 오로지 하위 컴포넌트로 전달하는 용도로만 쓰이는 컴포넌트들을 거치면서
React Component 트리의 한 부분에서 다른 부분으로 데이터를 전달하는 과정이다.
말이 좀 어려울테니 풀어서 설명하면, props를 전달할 때 중간 유통을 해주는 컴포넌트가 있는데,
그 컴포넌트들은 데이터가 필요하지 않지만 자식 컴포넌트로의 전달을 위해 props를 전달해주는 과정인 것이다.
말로만 하면 어려울테니 코드로 보자.
// ParentComponent.js
function ParentComponent() {
const [data, setData] = useState("initial data");
return (
<div>
// ParentComponent에서 ChildComponentA로 props 전달
<ChildComponentA data={data} />
</div>
);
}
// ChildComponentA.js
function ChildComponentA({ data }) {
return (
<div>
// ParentComponent에서 전달한 props를
// ChildComponentA를 거쳐 ChildComponentB로 전달
<ChildComponentB data={data} />
</div>
);
}
// ChildComponentB.js
function ChildComponentB({ data }) {
return (
<div>
// ParentComponent에서 전달한 props를
// ChildComponentA를 거쳐
// ChildComponentB를 거쳐 ChildeComponentC로 전달
<ChildComponentC data={data} />
</div>
);
}
// ChildComponentC.js
function ChildComponentC({ data }) {
// ParentComponent에서 전달한 props를
// ChildComponentA를 거쳐
// ChildComponentB를 거쳐
// ChildeComponentC로 전달한 것을 받아 씀.
return <div>{data}</div>;
}
일부러 주석을 자세히 작성하여 전달하는 역할이 얼마나 늘어나는지 더 와닿게 했다.
- Props Drilling의 문제점과 장단점
어떤가? 직관적으로 알기는 쉽지만 과정이 너무 번거롭게 느껴질 것이다.
지금이야 많은 과정을 거치지 않으니 props를 파악하기 어렵지 않겠지만 그 과정이 더 많아진다면?
props의 추적이 어려워지고 유지보수도 어려워진다.
내용을 정리하면 아래와 같다.
장점
- 직관적이기 때문에 컴포넌트 간 관계가 명확하고 데이터 흐름을 파악하기 쉽다.
단점
- 컴포넌트 간 중첩이 깊어질수록 코드의 가독성이 낮아진다.
- 데이터를 전달하는 과정에서 중간 단계의 컴포넌트가 추가되거나 사라질 때 유지보수가 어려워질 수 있다.
Props Drilling의 문제를 해결하는 방법
- 전역 상태 라이브러리 사용
Redux, MobX, Recoil과 같은 것을 사용하면 해당 값이 필요한 컴포넌트에서 직접 불러 사용할 수 있다.
- Children의 사용
부모 컴포넌트에서 컴포넌트 태그 사이의 내용을 자식 컴포넌트로 전달한다.
하나의 컴포넌트에서 값을 관리하기 때문에 값을 하위요소로 전달할 때 추적이 어렵지 않다.
// ParentComponent.js
function ParentComponent() {
const [data, setData] = useState("전달전달");
return (
<div>
<ChildComponentA>
<ChildComponentB>
<ChildComponentC data={data} />
</ChildComponentB>
</ChildComponentA>
</div>
);
}
// ChildComponentA.js
function ChildComponentA({ children }) {
return <div>{children}</div>;
}
// ChildComponentB.js
function ChildComponentB({ children }) {
return <div>{children}</div>;
}
// ChildComponentC.js
function ChildComponentC({ data }) {
return <div>{data}</div>;
}
✨ 마무리