본문 바로가기

개발 공부

Prop Drilling

Front-end 코드 작성 시 props가 너무 깊게 내려가거나, 중간 컴포넌트는 쓰지 않지만 props만 패스하는 경우가 있을 수 있습니다.

이 문제의 이름이 바로 Prop Drilling입니다.


Prop Drilling

Prop Drilling이란, 부모 컴포넌트에서 자식 → 손자 → 증손자… 이런 식으로
데이터(props)를 계속 전달해야 하는 현상을 말합니다.

// App.tsx
function App() {
  const user = { name: '유향', age: 27 };
  return <Parent user={user} />;
}

// Parent.tsx
function Parent({ user }: { user: { name: string; age: number } }) {
  return <Child user={user} />;
}

// Child.tsx
function Child({ user }: { user: { name: string; age: number } }) {
  return <GrandChild user={user} />;
}

// GrandChild.tsx
function GrandChild({ user }: { user: { name: string; age: number } }) {
  return <div>{user.name}님 안녕하세요!</div>;
}
  • 이 예제에서 실제로 user를 사용하는 건 마지막 GrandChild 뿐이지만, 중간의 Parent와 Child도 그 데이터를 전달하기 위해 props를 계속 이어가야 하죠.
  • 이것이 바로 Prop Drilling 문제입니다.

 


왜 문제가 될까?

 

문제점 설명
유지보수성 저하 중간 컴포넌트가 많을수록 props 수정 시 모든 단계에서 변경 필요
불필요한 리렌더링 상위 데이터 변경 시, 전달만 하는 중간 컴포넌트까지 리렌더링됨
가독성 저하 데이터 흐름을 추적하기 어려워짐
  • 결국 컴포넌트 구조가 커질수록 코드의 복잡도가 급격히 올라갑니다.

 


 

해결책 1 — 조합(Composition) 패턴 활용

조합(Composition) 패턴을 사용하면 부모 컴포넌트가 자식 컴포넌트에 Props를 일일이 전달해야 하는 Prop Drilling 문제를 완화할 수 있어요.

더 나아가, 조합 패턴은 불필요한 중간 추상화를 제거하여 개발자가 각 컴포넌트의 역할과 의도를 보다 명확하게 이해할 수 있도록 돕습니다.

function ItemEditModal({ open, items, recommendedItems, onConfirm, onClose }) {
  const [keyword, setKeyword] = useState("");

  return (
    <Modal open={open} onClose={onClose}>
      <ItemEditBody
        keyword={keyword}
        onKeywordChange={setKeyword}
        onClose={onClose}
      >
        <ItemEditList
          keyword={keyword}
          items={items}
          recommendedItems={recommendedItems}
          onConfirm={onConfirm}
        />
      </ItemEditBody>
    </Modal>
  );
}

function ItemEditBody({ children, keyword, onKeywordChange, onClose }) {
  return (
    <>
      <div style={{ display: "flex", justifyContent: "space-between" }}>
        <Input
          value={keyword}
          onChange={(e) => onKeywordChange(e.target.value)}
        />
        <Button onClick={onClose}>닫기</Button>
      </div>
      {children}
    </>
  );
}

 

  • 위의 예시처럼 children을 사용해 필요한 컴포넌트를 부모에서 작성하도록 하면 불필요한 Props Drilling을 줄일 수 있습니다.
  • 하지만, 조합 패턴만으로는 해결되지 않는 경우도 있고, 컴포넌트 트리 구조가 깊어지면 여전히 문제가 발생할 수 있어요.
  • 위의 예시에서도 ItemEditModal 컴포넌트는 여전히 items와 recommendedItems를 Props Drilling하고 있죠.

 


 

해결책 2 — Context API

 

Context API는 React에서 제공하는 전역 상태 공유 도구입니다.
중간 컴포넌트를 거치지 않고도, 필요한 하위 컴포넌트들이 바로 데이터에 접근할 수 있죠.

 

import React, { createContext, useContext } from 'react';

// 1 Context 생성
const UserContext = createContext<{ name: string } | null>(null);

// 2️ Provider로 감싸서 user 값 공유
function App() {
  const user = { name: '유향' };

  return (
    <UserContext.Provider value={user}>
      <Parent />
    </UserContext.Provider>
  );
}

// 3️ 중간 컴포넌트는 props 필요 없음
function Parent() {
  return <Child />;
}

function Child() {
  return <GrandChild />;
}

// 4️ 필요한 곳(GrandChild)에서 useContext로 바로 접근
function GrandChild() {
  const user = useContext(UserContext);
  return <h2>안녕하세요, {user?.name}님!</h2>;
}
  • 이제 어디서든 접근할 수 있습니다.
  • 이렇게 하면 더 이상 props를 전달할 필요가 없습니다.

 

 


Composition vs Context API — 언제 어떤 걸 쓸까?

 

상황 추천
특정 하위 컴포넌트만 데이터가 필요함 Composition 패턴
여러 계층에서 공통 상태를 써야 함 Context API
상태 변화가 거의 없는 정적 데이터 Composition (성능 손해 없음)
자주 바뀌는 전역 상태 Context (또는 Redux, Zustand 등)

 

 

 

'개발 공부' 카테고리의 다른 글

Prisma 스키마 (2) - 인덱스, 유니크, 복합키  (0) 2025.11.01
Prisma 스키마 (1)  (0) 2025.10.31
DFS, BFS  (0) 2025.10.08
Getter, Setter  (0) 2025.09.30
onAnimationStart, onShow  (0) 2025.09.28