본문 바로가기
IT/React Basic

[React] 초급 개념11 - Props Drilling과 해결 방법

by Echinacea 2025. 2. 26.
반응형

리액트에서 컴포넌트 간 데이터를 전달할 때 props를 사용합니다. 하지만, 깊이 중첩된 컴포넌트에서 여러 단계에 걸쳐 props를 전달하는 경우 Props Drilling(프롭스 드릴링) 문제가 발생할 수 있습니다.

 

 

왜 Props Drilling이 문제가 될까?

  • 중간 컴포넌트가 실제로 필요하지 않은 props를 전달해야 함.
  • 유지보수가 어려워지고, 코드 가독성이 저하됨.
  • 컴포넌트의 재사용성이 낮아짐.

 

Props Drilling을 해결하는 방법

  • Context API 사용 → 전역 상태를 제공하여 중간 컴포넌트 없이 데이터 공유 가능.
  • Redux, Recoil 등 상태 관리 라이브러리 사용 → 복잡한 상태 관리 필요 시 적합.
  • 컴포넌트 구조 최적화 → props를 최소화하고, 필요한 곳에서만 사용.

 

 

🔸 1. Props Drilling이란?

부모 컴포넌트의 데이터를 여러 단계 아래의 자식 컴포넌트로 전달하는 과정

 

 

✅ 예제: Props Drilling 발생

function Parent() {
  const userName = "Alice";
  return <Child userName={userName} />;
}

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

function GrandChild({ userName }) {
  return <h1>안녕하세요, {userName}님!</h1>;
}

 

📌 설명:

  • Parent에서 GrandChild까지 props를 직접 전달해야 하는 문제 발생.
  • Child 컴포넌트는 userName을 직접 사용하지 않지만, 불필요하게 props를 전달해야 함.

💡 이 방식의 단점:

  • 컴포넌트 계층이 깊어질수록 props 전달 과정이 복잡해짐.
  • 중간 컴포넌트가 불필요한 props를 전달하는 역할만 하게 됨.

 

 

🔸 2. Context API를 활용한 해결 방법

Context API를 사용하면 전역적으로 데이터를 관리하고 중간 컴포넌트를 거치지 않고 값을 전달할 수 있음.

 

 

✅ 예제: Context API 적용하기

import { createContext, useContext } from "react";

const UserContext = createContext();

function Parent() {
  return (
    <UserContext.Provider value="Alice">
      <Child />
    </UserContext.Provider>
  );
}

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

function GrandChild() {
  const userName = useContext(UserContext);
  return <h1>안녕하세요, {userName}님!</h1>;
}

 

📌 설명:

  • UserContext를 생성하여 Provider에서 전역 상태를 제공.
  • useContext(UserContext)를 사용하여 GrandChild에서 userName을 바로 가져옴.
  • 중간 컴포넌트(Child)는 더 이상 props를 전달할 필요 없음.

💡 이 방식의 장점:

  • props를 여러 단계 전달하지 않아도 됨 → 코드 간결화.
  • 여러 컴포넌트에서 동일한 데이터를 쉽게 공유 가능.

 

 

🔸 3. 상태 관리 라이브러리를 활용한 해결 방법

Redux, Recoil 같은 상태 관리 라이브러리를 사용하면 더 복잡한 상태 관리 가능

 

✅ 예제: Redux를 활용한 전역 상태 관리

import { createStore } from "redux";
import { Provider, useSelector, useDispatch } from "react-redux";

const initialState = { userName: "Alice" };

function reducer(state = initialState, action) {
  switch (action.type) {
    case "CHANGE_NAME":
      return { ...state, userName: action.payload };
    default:
      return state;
  }
}

const store = createStore(reducer);

function Parent() {
  return (
    <Provider store={store}>
      <Child />
    </Provider>
  );
}

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

function GrandChild() {
  const userName = useSelector(state => state.userName);
  return <h1>안녕하세요, {userName}님!</h1>;
}

 

📌 설명:

  • Redux를 활용하여 userName을 전역 상태로 관리.
  • useSelector를 사용하여 GrandChild에서 직접 상태를 가져옴.
  • 여러 컴포넌트에서 일관된 데이터 공유 가능.

💡 이 방식의 장점:

  • 상태를 체계적으로 관리할 수 있어 유지보수 용이.
  • 규모가 큰 프로젝트에서 복잡한 상태 관리에 유리.

 

 

🔸 4. 컴포넌트 구조 최적화

컴포넌트 설계를 개선하여 불필요한 Props Drilling을 방지할 수 있음

 

 

✅ 예제: 컨테이너 컴포넌트 활용

function Parent() {
  const userName = "Alice";
  return <Child userName={userName} />;
}

function Child({ userName }) {
  return <GrandChildDisplay userName={userName} />;
}

function GrandChildDisplay({ userName }) {
  return <h1>안녕하세요, {userName}님!</h1>;
}

 

📌 설명:

  • GrandChild가 불필요한 역할을 하지 않도록 분리하여 최적화.
  • GrandChildDisplay가 userName을 직접 받도록 변경.

💡 이 방식의 장점:

  • 불필요한 props 전달을 최소화하여 가독성 향상.
  • 재사용성이 높은 컴포넌트 구조 설계 가능.

 

 

🔸 5. 개념 요약

Props Drilling은 불필요한 props 전달로 인해 코드 가독성과 유지보수가 어려워지는 문제
Context API를 사용하면 중간 컴포넌트를 거치지 않고 전역 데이터를 쉽게 공유 가능
Redux, Recoil과 같은 상태 관리 라이브러리를 사용하면 대규모 애플리케이션에서 더욱 효과적
컴포넌트 구조를 개선하여 Props Drilling을 최소화할 수 있음
적절한 방법을 선택하여 효율적인 상태 관리를 할 것


 

반응형

댓글