Compound Component 패턴과 Context API의 연관성

OlMinJe·2025년 12월 30일

React

목록 보기
19/19

최근 TabsCalendar와 같은 복잡한 UI를 라이브러리 없이 순수 컴포넌트로 직접 구현하면서, Shadcn UI나 Radix UI가 왜 그렇게 코드를 짰는지 이해했다. 특히 Compound Component(복합 컴포넌트) 패턴을 직접 적용해 보니, 이게 왜 Context API랑 찰떡궁합인지 알아갔으며, 이에대해 알게된 내용을 정리해본다.

1. Compound Component 패턴이란?

Compound Component 패턴은 하나의 작업을 수행하기 위해 여러 개의 하위 컴포넌트들이 협력하여 하나의 단위로 동작하는 설계 방식이다.

이해한 대로 비유하자면 ‘조립식 장난감’ 같다. 부모 컴포넌트가 "넌 이렇게 생겨야 해!"라고 모든 걸 정해주는 게 아니라, 사용자가 필요한 부품(하위 컴포넌트)을 골라 원하는 위치에 끼워 맞추면서 전체 기능을 완성하는 식!

❌ 패턴 적용 전 (Props 중심)

부모 컴포넌트에 수많은 Props를 전달해야 하며, 내부 구조를 변경하기 어렵다.

<Tabs 
  items={items} 
  defaultValue="tab1" 
  onTabChange={...} 
  tabListClassName="..."
/>

✅ 패턴 적용 후 (구조 중심)

각 역할이 명확히 분리된 하위 컴포넌트를 조합할 수 있다. 직관적 미쳤음

<TabsRoot defaultValue="tab1">
  <TabsList>
    <TabsTrigger value="tab1">1</TabsTrigger>
  </TabsList>
  <TabsContent value="tab1">내용1</TabsContent>
</TabsRoot>

2. Compound Component와 Context API의 연관성

Compound 패턴을 만들 때 Context API는 부품들을 연결해 주는 역할을 해준다. (like 블루투스..? 무선..?)

1) 명시적인 Props 전달 제거 (Props Drilling 방지)

TabsRoot가 가진 activeTab 상태를 TabsTriggerTabsContent가 알기 위해서는 원래 부모를 거쳐 Props로 전달받아야 한다.
하지만 Context API를 사용하면 하위 컴포넌트들이 어디에 위치하든 상관없이 필요한 상태에 직접 접근할 수 있게 된다.

2) 유연한 레이아웃 구성

Context API 덕분에 하위 컴포넌트의 순서나 중첩 구조가 자유로워졌다.
TabsList 안에 TabsTrigger를 넣든, 별도의 div로 감싸든 상관없이 Context를 통해 상태를 공유하기 때문에 UI 배치가 자유롭다.

3) 캡슐화와 사용성 향상

탭 전환 함수나 현재 활성화된 값 같은 복잡한 로직은 Context 안으로 싹 숨겨버리고(캡슐화), 사용자에게는 필요한 컴포넌트만 딱 보여줄 수 있다. 쓰는 사람 입장에서는 복잡한 계산 없이 UI를 선언적으로 툭툭 가져다 쓰기만 하면 되는!


직접 구현해 보니 Compound Component가 ‘구조적인 자유’를 준다면, Context API는 그 자유 속에서도 ‘데이터의 일관성’을 꽉 잡아주는 느낌이었다. 라이브러리 없이 순수 컴포넌트를 만들 때 이 조합은 정말 강력하고 괜찮은 선택인 것 같음!

profile
큐트걸

0개의 댓글