Compound Component Pattern

예진·2024년 3월 11일

개인 공부

목록 보기
6/15

🔥 Compound Component Pattern

: 자식 컴포넌트들이 부모 컴포넌트 내부의 상태를 공유하면서 비즈니스 로직과 사용자 인터페이스와 관련된 부분을 구분하는 React 디자인 패턴

→ 하나의 복합적인 컴포넌트를 여러 개의 서브 컴포넌트로 분리하고, 사용자가 원하는 형태로 서브 컴포넌트들을 조립하여 구성하는 디자인 패턴

HTML 예시

- 가장 쉬운 대표적인 예시 <select>, <option> 태그

<select>
  <option value="react">React</option>
  <option value="next">Next</option>
  <option value="angular">Angular</option>
</select>

→ 부모 컴포넌트(select)가 상태를 관리하고, 자식 컴포넌트(option)들이 그 상태를 공유하면서 하나의 완성된 UI 구성

이처럼 부모와 자식 컴포넌트가 유기적으로 결합되어 동작하는 구조가 Compound Component Pattern의 핵심!

Compound Component Pattern 왜 사용할까?

  • 복잡한 UI 구성: 다양한 기능을 포함하는 복잡한 UI를 작은 단위로 나누어 구성할 때 적합함
  • 재사용성 필요: 여러 곳에서 동일하거나 유사한 기능을 사용해야 할 때 유용함
  • 모듈성 확보: 기능을 독립적인 작은 컴포넌트로 나누어 개발하고 테스트해야 할 때 적절함

장점

  1. 자유로운 커스터마이징
    → 하위 컴포넌트를 자유롭게 추가하거나 제거할 수 있음
  2. Props Drilling 방지
    → 상위 컴포넌트에서 하위 컴포넌트로 props를 연쇄적으로 전달하는 문제를 해결할 수 있음
  3. 직관적인 API
    → 컴포넌트 사용자에게 명확하고 이해하기 쉬운 인터페이스를 제공함

구현 방법

Compound Component Pattern은 보통 React의 Context API를 활용해 구현함
→ 부모 컴포넌트의 상태와 함수를 자식 컴포넌트에서 props 없이 바로 사용 가능

import { createContext, useContext, useState } from "react";

const CardContext = createContext();

export function Card({ children }) {
  const [selected, setSelected] = useState(null);
  return (
    <CardContext.Provider value={{ selected, setSelected }}>
      <div className="card">{children}</div>
    </CardContext.Provider>
  );
}

Card.Title = function CardTitle({ children }) {
  return <h2>{children}</h2>;
};

Card.Body = function CardBody({ children }) {
  return <div>{children}</div>;
};

Card.Item = function CardItem({ children }) {
  const { selected, setSelected } = useContext(CardContext);
  return (
    <div
      style={{
        background: selected === children ? "skyblue" : "white",
        cursor: "pointer",
      }}
      onClick={() => setSelected(children)}
    >
      {children}
    </div>
  );
};
<Card>
  <Card.Title>Component compound pattern</Card.Title>
  <Card.Body>
    <Card.Item>부모와 자식으로 UI와 논리 분리</Card.Item>
	<Card.Item>Props 대신 자식 컴포넌트로 전달</Card.Item>
	<Card.Item>컴포넌트의 재사용성 향상</Card.Item>
  </Card.Body>
</Card>

위처럼 작성하면 코드의 가독성이 높아지고, 컴포넌트의 구조를 직관적으로 이해할 수 있음.

주의사항

  • Context 남용 주의
    너무 많은 상태나 함수를 context에 넣으면 불필요한 리렌더링이 발생할 수 있음
  • 컴포넌트 계층 구조
    자식 컴포넌트가 반드시 부모 컴포넌트 내에 있어야 context에 접근 가능함

언제 사용하면 좋을까?

  • 토글, 드롭다운, 탭, 아코디언 등 여러 UI 요소가 상호작용하며 공통 상태를 공유해야 할 때
  • 복잡한 UI를 작은 컴포넌트로 쪼개고 싶을 때
profile
😊

0개의 댓글