pile·
프론트엔드·카카오 엔터테인먼트 FE카카오 엔터테인먼트 FE·

합성 컴포넌트로 재사용성 극대화하기

카카오엔터테인먼트 FE 팀이 Dialog Modal 컴포넌트를 사례로, 단순 props 방식의 한계를 합성 컴포넌트(Composition Component) 패턴으로 어떻게 극복했는지를 3단계 리팩토링 흐름으로 설명하는 글이다. HTML의 select/option 구조에서 영감을 받아 서브 컴포넌트를 독립 구현하고 Object.assign으로 묶어 Dialog.Title 형태로 노출하는 실전 패턴을 다룬다.

핵심 포인트
  • 단순 props 방식은 요구사항이 늘어날수록 props 폭발 문제가 발생하고 컴포넌트 위치까지 구현 시점에 고정되어 유연성을 잃음
  • 합성 컴포넌트 패턴은 하나의 컴포넌트를 여러 서브 컴포넌트로 분리, 사용하는 쪽에서 조합 방식과 배치를 자유롭게 결정
  • HTML select/option이 대표적 합성 컴포넌트 예시, React에서 Dialog.Title, Dialog.LabelButton 등으로 동일 개념 구현
  • DialogMain에서 children의 type을 분류해 LabelButton은 하단 고정, Dimmed는 스택 아래 등 레이아웃 규칙 유지 가능
  • Object.assign(DialogMain, { Title: DialogTitle, LabelButton: DialogLabelButton })으로 단일 네임스페이스 export
  • props 방식 대비 사용 측에서 구성 요소 순서와 조합을 자유롭게 결정할 수 있어 유지보수성과 가독성 크게 향상
상세 정리
  • Step 1 최초 구현: isOpen, title, buttonLabel, onClickButton 4개 props로 단순 Dialog 구현, 재사용 가능하지만 확장성 제한
  • Step 2 추가 요구사항: 체크박스, description, 버튼 추가로 props가 3개씩 늘어나는 구조, 컴포넌트 내 배치가 구현 시점에 고정
  • Step 2의 문제: 컴포넌트에 역사가 쌓일수록 사이드이펙트 위험 증가, checkbox와 description 순서를 바꾸려면 또 props 추가 필요
  • Step 3 합성 컴포넌트: 서브 컴포넌트(DialogTitle, DialogLabelButton 등)와 메인 컴포넌트(DialogMain)를 분리하여 구현
  • 서브 컴포넌트 특징: 각각 독립으로는 의미 없지만 조합 시 완성, children과 최소 props만 받아 스타일만 담당
  • DialogMain은 children을 받아 React.createPortal로 document.body에 렌더링, isOpen 조건 처리
  • 위치 고정 서브 컴포넌트: Children.toArray + isValidElement + child.type 비교로 분류 후 배치, LabelButton 최대 2개로 슬라이싱
  • const DialogLabelButtonType = (<DialogLabelButton />).type 패턴으로 타입 참조 추출
  • Object.assign(DialogMain, { Title: DialogTitle, LabelButton: DialogLabelButton })으로 단일 Dialog 네임스페이스 구성
  • 사용 예: Dialog isOpen={open} 안에 Dialog.Title, Dialog.LabelButton을 필요한 순서로 자유롭게 배치
  • checkbox가 description 위에 오는 변형도 추가 props 없이 사용 측에서 순서만 바꾸면 처리 가능
왜 읽나props 폭발로 고통받는 공통 컴포넌트를 합성 패턴으로 리팩토링하는 3단계 흐름과 Object.assign export 디테일을 실전 코드로 바로 적용할 수 있다.
카카오 엔터테인먼트 FE
카카오 엔터테인먼트 FE 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 프론트엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    항공 프론트엔드 구축기 (7/10): 창구를 하나만 두었습니다

    여기어때 항공 서비스 프론트엔드가 웹과 앱 웹뷰 두 환경에서 동일한 함수 호출로 동작하는 앱 브릿지 추상화 레이어를 설계한 과정을 다룬다. iOS·안드로이드 규약 차이와 "웹에 존재하지 않는 브릿지를 어떻게 호출하나"라는 문제를 단일 추상화 층으로 해결한 구현 사례다.

    요약 이어보기
    #react#typescript#webview+2