프롭스 드릴링(Props Drilling)이란 상위 컴포넌트가 하위 컴포넌트로 Props를 전달할 때 발생하는 구조적 문제를 말한다.
예를 들어, 최상위 컴포넌트가 직계비속 중 사촌쯤 되는 하위 컴포넌트에게 데이터를 전달해야 한다고 생각해 보자.
이 데이터는 최상위 컴포넌트의 하위(자식) 컴포넌트를 경유하고 또 그 컴포넌트의 자식을 건너고, 또 일촌을 건너야 비로소 전달되는 구조적인 문제를 갖고 있다.
즉, 그저 경유하기만 하는 컴포넌트가 최소 2개나 있다는 뜻이다.
여기서 만약 상태 데이터의 이름이나 직/간접적으로 참조하고 있는 함수의 이름이 변경되어야 한다면 어떤 문제가 발생할까?
이 데이터가 경유하고 있는 모든 컴포넌트를 열어 하나씩 수정해야 하는 아주 끔찍한 일이 발생할 것이다.
이를 프롭스 드릴링이라 부르며 이러한 구조적 문제는 단방향 데이터 흐름만을 지원하는 리액트의 고질적인 문제라고 볼 수 있다.
시간과 비용을 절약하기 위해선 반드시 해결되어야 하는 문제인데 다행히 Provider 즉, 공급자 컴포넌트로 이를 해결할 수 있다.
이 공급자 컴포넌트는 자손에 해당하는 컴포넌트들에게도 별 다른 경유 없이 데이터를 전달해 주는데 사람으로 치면 큰 집에 살고 계신 큰 아버지라 생각하면 된다.
최상위 컴포넌트는 공급자 컴포넌트에게 모든 데이터를 전달하고 공급자 컴포넌트는 직통으로 하위 컴포넌트에게 이 데이터를 전달하게 된다.
이 공급자 컴포넌트는 리액트의 createContext 훅으로 생성할 수 있는데 아래 예시를 보면 금방 이해할 수 있다.
// App.js
export const ComContext = React.createContext(defaultValue);
const App = () =>{
return(
<ComContext.Provider value = {/*Values to Share Globally*/ }>
{/* 이 프로그램을 구성하는 요소 즉, 자식 컴포넌트들을 포함하면 된다.*/}
</ComContext.Provider>
);
}
export default App;
공급자 컴포넌트 태그 사이에 위치한 컴포넌트들은 태그에서 지정한 속성 값(또는 Props)을 전역적으로 공유하게 된다.
앞에서 말한 상태 데이터를 전달받는 컴포넌트가 있다면 해당 컴포넌트는 더 이상 Props를 따로 전달받을 필요가 없다.
아래 예시를 보자.
import LComp from "./LComp";
const layOver = (/*{onCreate, onTimer, onPaint}*/) => {
return(
<div>
<h2>Example Code</h2>
<div>
/*{ExampleList.map((e)=>(<LComp val = {e.list1} create={onCreate} timer={onTimer} paint={onPaint}}))}*/
{ExampleList.map((e)=>(<LComp val = {e.list1} />))}
</div>
</div>
);
}
export default layOver;
주석 처리된 부분이 원래 작성하던 코드라 생각하면 된다.
여기서 주의할 건 직계, 그러니까 바로 아래의 하위 컴포넌트가 layOver 컴포넌트이고 이 컴포넌트가 Props로 받고 있는 onCreate, onTimer, onPaint 등의 함수는 더 하위의 컴포넌트로 전달될 값이다.
위 예시에서 주석 처리한 {ExampleList.map...} 구문을 보면 LComp 컴포넌트로 자신이 받은 함수를 그대로 전달하고 있다.
즉, layOver 컴포넌트는 최상위 컴포넌트로부터 LComp로 함수를 전달하기 위해 그저 경유하는 중간 다리 역할이란 뜻이다.
이제 LComp를 보자.
import React, {useContext} from "react";
import {ComContext} from "./App";
const LComp = (/*{onCreate, onTimer, onPaint}*/) =>{
const {onCreate, onTimer, onPaint} = useContext(ComContext);
// 사용중...
};
export default LComp;
layOver를 경유하여 전달받던 함수를 이제는 컨텍스트로 직접 받고 있다.
useContext 구문은 컨텍스트에 포함된 함수를 사용하겠다는 의사표시이며 이렇게 불러온 함수는 해당 컴포넌트 내에서 얼마든지 사용할 수 있다.
공급자 컴포넌트는 말 그대로 컴포넌트이기 때문에 함수와 상태 데이터를 따로 관리해야 하는 상황이라면 그 개수만큼 공급자 컴포넌트를 만들어 사용하면 된다.
'컴퓨터 > Frontend' 카테고리의 다른 글
[React] 최적화(3) - useCalback, 함수형 업데이트 (0) | 2023.03.27 |
---|---|
[React] 최적화(2) - Raect.memo (0) | 2023.03.24 |
[React] 최적화(1) - useMemo (0) | 2023.03.23 |
[Javascript] 비동기 처리(3) - async, await (0) | 2023.03.18 |
[Javascript] 비동기 처리(2) - Promise 객체 (0) | 2023.03.18 |
댓글