[React] Compound Component 패턴 + Context 이해하기

2025. 5. 6. 16:56·Library & Runtime/React

 

🔍 Compound Component 패턴이란?

Compound Component(컴파운드 컴포넌트) 패턴은 부모와 자식 컴포넌트가 자연스럽게 협력하는 구조를 만들기 위한 패턴이다.

부모가 Context를 제공하고, 자식 컴포넌트들이 props 없이 그 상태를 자유롭게 사용할 수 있다.

이 패턴은 Select, Accordion, Tabs, Modal Step Form과 같은 UI를 구성할 때 자주 사용된다.

Toggle 예제를 통해 이 패턴을 이해하고, Context의 역할을 알아보자.

 

🔍 Context란?

Context는 여러 컴포넌트들이 데이터를 공유할 수 있도록 도와주는 기능이다.

React에서는 일반적으로 부모 컴포넌트에서 자식으로 데이터를 props를 통해 넘긴다.
하지만 컴포넌트 깊이가 깊어질수록 이 과정이 번거로워지는데, 이를 props 드릴링이라 한다.

 

Context를 사용하면 이 번거로움을 해결할 수 있다.
부모가 제공(provider)한 값을 자식 어디서든(useContext) 바로 꺼내 쓸 수 있기 때문이다.

const MyContext = createContext(초기값);

자식 컴포넌트에서는 다음과 같이 사용한다.

const value = useContext(MyContext);

 

🧩 예제 코드

  • Toggle.tsx
import { createContext, useContext, useState, ReactNode } from 'react';

// context 공간을 만듦
const ToggleContext = createContext<{
  on: boolean; // 불 켜짐/꺼짐 상태
  toggle: () => void; // 상태를 바꾸는 함수
} | null>(null);

// 부모 컴포넌트
// 상태를 만들고 자식 컴포넌트에게 context로 전달
const Toggle = ({ children }: { children: ReactNode }) => {
  const [on, setOn] = useState(false); // 상태 생성
  const toggle = () => setOn(o => !o); // 상태 변경 함수

  // 자식 컴포넌트들이 context 데이터에 접근 가능하도록 함
  return <ToggleContext.Provider value={{ on, toggle }}>{children}</ToggleContext.Provider>;
};

// 자식 컴포넌트: On
const ToggleOn = ({ children }: { children: ReactNode }) => {
  const context = useContext(ToggleContext); // context 가져옴
  if (!context) throw new Error('Toggle.On must be used within <Toggle>');

  return context.on ? <>{children}</> : null;
};

Toggle.On = ToggleOn;

// 자식 컴포넌트: Off
const ToggleOff = ({ children }: { children: ReactNode }) => {
  const context = useContext(ToggleContext);
  if (!context) throw new Error('Toggle.Off must be used within <Toggle>');

  return !context.on ? <>{children}</> : null;
};

Toggle.Off = ToggleOff;

// 자식 컴포넌트: Button
const ToggleButton = () => {
  const context = useContext(ToggleContext);
  if (!context) throw new Error('Toggle.Button must be used within <Toggle>');

  return <button onClick={context.toggle}>토글 전환</button>;
};

Toggle.Button = ToggleButton;

export default Toggle;
  • CompoundExample.tsx
import Toggle from './Toggle';

// 부모 컴포넌트와 자식 컴포넌트들이 자연스럽게 함께 동작하도록 만든 패턴
// Select, Accordion, Tabs 등
const CompoundExample = () => {
  return (
    <div style={{ padding: 20 }}>
      <h2>Compound Component 패턴 실험</h2>
      <Toggle>
        <Toggle.On>🔆 켜졌어요!</Toggle.On>
        <Toggle.Off>🌙 꺼졌어요.</Toggle.Off>
        <Toggle.Button />
      </Toggle>
    </div>
  );
};

export default CompoundExample;

 

🧩 정리

  • props 없이 부모 상태를 자식들이 자유롭게 사용할 수 있다.
  • 복잡한 UI에서도 코드 재사용성과 유지보수성이 높아진다.
  • 컴포넌트 분리: On, Off, Button이 각각 독립적으로 존재하면서 자유롭게 조합된다.
  • 에러 방지: context가 없으면 명확한 에러가 발생하도록 처리하였다.
참고: context가 null인 경우 에러를 발생시키는 부분은 유지보수를 쉽게 만들어 준다.
Toggle 외부에서 잘못 사용하면 바로 알 수 있다.

 

 

✏️ (참고) 함수 이름 명시

// ❌ 익명 함수
Toggle.On = ({ ... }) => { ... };

// ✅ 이름 있는 함수
const ToggleOn = ({ ... }) => { ... };
Toggle.On = ToggleOn;

처음에는 익명 함수 형태로 작성했는데 eslint 경고가 떴다.

익명 함수(화살표 함수)는 React 개발 도구, ESLint, HMR(Hot Reload)에서 컴포넌트 이름을 제대로 인식하지 못한다고 한다.
이름 있는 함수로 선언하면 React가 컴포넌트임을 확신할 수 있다고 하여 고쳐주었다.

 

반응형

'Library & Runtime > React' 카테고리의 다른 글

[React] Control Props 패턴 : Controlled vs Uncontrolled  (0) 2025.05.07
[React] Virtual Scroll(가상 스크롤)로 렌더링 최적화하기 (react-window)  (0) 2025.05.05
[React] 계산/렌더링 최적화: useMemo + React.memo 실험  (0) 2025.05.04
[React] 무거운 연산 최적화 : 일반 계산 vs useMemo  (0) 2025.05.03
'Library & Runtime/React' 카테고리의 다른 글
  • [React] Control Props 패턴 : Controlled vs Uncontrolled
  • [React] Virtual Scroll(가상 스크롤)로 렌더링 최적화하기 (react-window)
  • [React] 계산/렌더링 최적화: useMemo + React.memo 실험
  • [React] 무거운 연산 최적화 : 일반 계산 vs useMemo
올콩
올콩
콩 심은 데 콩 난다
  • 올콩
    콩스토리
    올콩
  • 전체
    오늘
    어제
    • 분류 전체보기 (147) N
      • SSAFY (10)
      • Algorithm (73) N
        • 이론 (5)
        • 백준 (BOJ) (67) N
        • 프로그래머스 (1)
      • Language (9)
        • JavaScript (0)
        • TypeScript (0)
        • Java (9)
        • Python (0)
      • Library & Runtime (15)
        • React (13)
        • Node.js (2)
      • Framework (9)
        • 이론 (2)
        • Next.js (3)
        • Vue (4)
      • DevOps (3)
        • Git (3)
      • WEB (18)
        • HTML (9)
        • error (7)
        • etc (2)
      • Computer (5)
        • 자격증 (2)
        • tip (2)
        • etc (1)
      • CS (5)
        • Network (1)
        • Blockchain (4)
  • 블로그 메뉴

    • GitHub
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    해시
    Algorithm
    싸피
    kakaomap
    파이썬
    재귀
    오블완
    티스토리챌린지
    Next.js
    DP
    SSAFY
    우선순위큐
    딕셔너리
    렌더링최적화
    Java
    SSAFYcial
    Error
    블록체인
    vue
    github
    bfs
    React
    누적합
    자바
    dfs
    강의
    카카오맵
    백준
    알고리즘
    html5
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
올콩
[React] Compound Component 패턴 + Context 이해하기
상단으로

티스토리툴바