TIL - 20250908

juni·2025년 9월 8일

TIL

목록 보기
119/317

0908 React useContext: 전역 상태 관리와 Prop Drilling 해결


✅ 1. Context API란? (문제: Prop Drilling)

  • 문제점 (Prop Drilling): React의 기본 데이터 흐름은 Props를 통해 부모에서 자식으로 이어집es. 하지만 앱의 특정 상태(e.g., 로그인 정보, 테마, 장바구니 데이터)가 최상위 컴포넌트에 있는데, 이 상태가 아주 깊숙이 있는 하위 컴포넌트에서 필요할 경우, 중간에 있는 모든 컴포넌트들을 거쳐 Props를 전달해야 합니다. 이를 "Prop Drilling"이라고 하며, 코드를 복잡하고 유지보수하기 어렵게 만듭니다.

  • 해결책 (Context API): Context는 React 컴포넌트 트리 안에서 전역적으로(globally) 데이터를 공유할 수 있는 방법을 제공합니다. Props를 통해 단계별로 데이터를 전달할 필요 없이, Context는 필요한 컴포넌트가 데이터를 직접 소비할 수 있는 "데이터 터널" 또는 "텔레포트" 역할을 합니다.


✅ 2. Context 생성 및 제공 (Provider)

  • Context를 사용하기 위해서는 먼저 Context 객체를 생성하고, 데이터를 제공할 Provider 컴포넌트로 앱의 일부를 감싸야 합니다.
  1. createContext: Context 객체를 생성합니다. 초기값은 Provider가 없을 때 사용될 기본값입니다.
  2. Provider 컴포넌트: 생성한 Context 객체에 포함된 Provider 컴포넌트로, 하위 컴포넌트들에게 Context 데이터를 전달하는 역할을 합니다. value prop으로 전달할 데이터를 지정합니다.
  3. 상태 관리 로직 캡슐화: 보통 Context Provider 자체를 별도의 컴포넌트(CartProvider)로 만들어, 관련된 상태(useState)와 상태 변경 함수들을 그 안에 모두 캡슐화하는 패턴을 사용합니다.
// contexts/CartContext.js
import { createContext, useState } from 'react';

// 1. Context 객체 생성
export const CartContext = createContext({
  items: [],
  addItem: (item) => {},
  removeItem: (id) => {},
  // ... 모달 제어 함수 등
});

// 3. 상태 관리 로직을 포함한 Provider 컴포넌트 생성
function CartProvider({ children }) {
  const [cartItems, setCartItems] = useState([]);

  function handleAddToCartItem(newItem) {
    // ... 장바구니 추가 로직 ...
  }
  
  function handleRemoveToCartItem(id) {
    // ... 장바구니 삭제 로직 ...
  }

  const ctxValue = {
    items: cartItems,
    addItem: handleAddItem,
    removeItem: handleRemoveItem,
  };

  // 2. Provider로 하위 컴포넌트를 감싸고, value prop으로 데이터 전달
  return (
    <CartContext.Provider value={initialValue}>
      {children}
    </CartContext.Provider>
  );
}

export default CartProvider;

✅ 3. Context 데이터 소비하기 (useContext)

  • Provider로 감싸진 하위 컴포넌트 어디에서든 useContext Hook을 사용하여 Context의 value에 접근할 수 있습니다.

✅ 4. Context 사용 시 주의사항: 불필요한 리렌더링

  • 제약사항: Context의 value가 변경되면, 해당 Context를 useContext로 구독하는 모든 컴포넌트가 리렌더링됩니다.
  • 문제: 만약 하나의 거대한 Context에 모든 상태(장바구니 배열, 모달 상태, 사용자 정보 등)를 다 넣으면, 아주 작은 상태 하나만 변경되어도 앱의 많은 부분이 불필요하게 리렌더링될 수 있습니다.
  • 해결책 (컴포넌트 분리 및 Context 분리):
    1. 컴포넌트 분리: Context를 구독하는 컴포넌트를 최대한 작게 유지하여, 리렌더링의 영향을 최소화합니다.
    2. Context 분리: 서로 관련 없는 상태들은 별개의 Context로 분리하는 것을 고려합니다. (e.g., CartContext, AuthContext, ThemeContext)

📌 요약

  • Context APIProp Drilling 문제를 해결하기 위해, 컴포넌트 트리에 전역적인 데이터를 제공하는 기능입니다.
  • createContext로 Context를 생성하고, 상태 관리 로직을 담은 Provider 컴포넌트로 앱을 감쌉니다.
  • 하위 컴포넌트에서는 useContext Hook을 사용하여 Props 전달 없이 데이터나 함수에 직접 접근할 수 있습니다.
  • 장바구니 배열, 모달 제어 함수 등 여러 컴포넌트에서 공유해야 하는 상태를 Context로 관리하면 코드 구조가 매우 깔끔해집니다.
  • 불필요한 리렌더링을 방지하기 위해, Context의 역할을 명확히 하고 적절히 분리하는 것이 중요합니다.

0개의 댓글