Blog

props drilling이 생겼던 구조와 당시 선택


5 min read

서론#

컴포넌트 구조가 단순할 때는
props를 내려주는 방식이 크게 문제되지 않는다.

하지만 상태를 상위로 끌어올리기 시작하면
자연스럽게 props drilling이 발생한다.

이 글은
props drilling이 실제로 문제가 되기 시작한 구조와,
그 시점에서 어떤 선택을 했는지에 대한 기록이다.

props drilling이 생겼던 구조#

게시글 목록 페이지에서
필터 상태를 상위 컴포넌트에서 관리하고 있었다.

구조는 대략 다음과 같았다.

<Page>
  <ListContainer>
    <ListHeader />
    <PostList>
      <PostItem />
    </PostList>
  </ListContainer>
</Page>

필터 상태는 Page에 있었고,
실제로 필요한 곳은 ListHeaderPostList였다.

그래서 props는 이렇게 흘러갔다.

<Page>
  <ListContainer filter={filter} onChangeFilter={setFilter}>
    <ListHeader filter={filter} onChangeFilter={setFilter} />
    <PostList filter={filter} />
  </ListContainer>
</Page>

문제는 ListContainer였다.

이 컴포넌트는
해당 props를 사용하지도 않으면서,
구조를 유지하기 위해 전달만 하고 있었다.

이 구조가 불편해진 지점#

props drilling 자체가 나쁜 것은 아니다.

하지만 이 구조에서는
다음과 같은 문제가 동시에 나타났다.

  • 중간 컴포넌트의 책임이 불명확해짐
  • props가 늘어날수록 컴포넌트 시그니처가 복잡해짐
  • 구조를 이해하려면 props 흐름을 끝까지 따라가야 함

특히 구조를 수정하거나
컴포넌트를 재사용하려고 할 때
불필요한 의존성이 발목을 잡았다.

Context API를 고려하게 된 지점#

이후 필터 상태를 사용하는 컴포넌트가 늘어나면서
상태의 성격이 분명해졌다.

  • 동일한 페이지 내 여러 컴포넌트에서 사용
  • props로 내려보내기에는 경로가 너무 김
  • 페이지를 벗어나면 필요 없음

이 시점에서
Context API가 자연스럽게 선택지로 올라왔다.

Context API 적용 예시 (간단 버전)#

// FilterContext.tsx
import { createContext, useContext, useState } from "react";

const FilterContext = createContext<{
  filter: string;
  setFilter: (value: string) => void;
} | null>(null);

export const FilterProvider = ({ children }: { children: React.ReactNode }) => {
  const [filter, setFilter] = useState("all");

  return <FilterContext.Provider value={{ filter, setFilter }}>{children}</FilterContext.Provider>;
};

export const useFilter = () => {
  const context = useContext(FilterContext);
  if (!context) throw new Error("FilterProvider 내부에서만 사용 가능합니다.");
  return context;
};
// Page.tsx
<FilterProvider>
  <ListContainer />
</FilterProvider>
// ListHeader.tsx
const { filter, setFilter } = useFilter();

Context를 써도 해결되지 않는 것#

Context를 도입했다고 해서
모든 문제가 사라지는 것은 아니었다.

  • Context는 전역 상태가 아니다
  • 남용하면 의존성이 보이지 않게 숨겨진다
  • 렌더링 범위에 대한 고려가 필요하다

그래서 Context는
props drilling을 없애기 위한 도구라기보다,
상태의 범위가 명확해졌을 때 사용하는 수단에 가까웠다.

정리#

props drilling은
구조가 잘못됐다는 신호라기보다,
상태의 위치를 다시 고민하라는 힌트에 가깝다.

그래서 중요한 것은
"props를 없애는 것"이 아니라,

  • 이 상태는 어디까지 영향을 미치는지
  • 정말 공통 상태인지
  • 페이지를 벗어나도 필요한지

를 먼저 판단하는 것이다.

Context API는
그 판단 이후에 등장하는 선택지 중 하나일 뿐이다.

8