기술 포스트

children과 합성 — 컴포넌트 안에 컴포넌트를 넣습니다


Article

Props로 데이터를 전달하는 방법은 배웠습니다. 그런데 컴포넌트에 텍스트나 숫자가 아니라, 다른 컴포넌트 자체를 넣고 싶을 때는 어떻게 할까요?

children이란

HTML에서 태그 안에 내용을 넣는 건 익숙할 겁니다.

<div>
  <p>안녕하세요</p>
</div>

React 컴포넌트도 똑같이 할 수 있습니다. 컴포넌트 태그 사이에 넣은 내용이 바로 children입니다.

<Card>
  <p>이 내용이 children입니다</p>
</Card>

Card 컴포넌트 입장에서는 <p>이 내용이 children입니다</p> 부분이 children으로 전달됩니다.

function Card({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  );
}

이렇게 하면 Card 컴포넌트는 어떤 내용이든 감싸는 껍데기 역할을 합니다. 안에 뭘 넣든 자유입니다.

퍼블리셔에게 익숙한 개념

퍼블리싱을 해봤다면 레이아웃 include 패턴을 써본 적이 있을 겁니다. header와 footer는 고정이고, 가운데 콘텐츠 영역만 페이지마다 바뀌는 구조입니다.

children이 바로 그 콘텐츠 영역을 비워두는 슬롯과 같은 개념입니다. 껍데기는 고정하고, 안에 들어갈 내용만 바꿔 끼우는 겁니다.

합성으로 유연한 레이아웃 만들기

이 패턴을 **합성(Composition)**이라고 부릅니다. 컴포넌트를 조합해서 더 큰 구조를 만드는 방식입니다.

간단한 Card 컴포넌트를 예로 들어보겠습니다.

function Card({ children }) {
  return (
    <div className="border rounded-lg p-4 shadow-sm">
      {children}
    </div>
  );
}

이 Card는 어디서든 재사용할 수 있습니다.

// 프로필 카드
<Card>
  <h2>민수</h2>
  <p>웹퍼블리셔</p>
</Card>

// 상품 카드
<Card>
  <img src="/product.jpg" alt="상품" />
  <p>29,000원</p>
</Card>

같은 Card 컴포넌트인데 안에 넣는 내용에 따라 전혀 다른 용도로 쓰이고 있습니다.

Layout 컴포넌트

실무에서 가장 많이 쓰이는 합성 패턴이 Layout 컴포넌트입니다.

function Layout({ children }) {
  return (
    <div>
      <header>헤더 영역</header>
      <main>{children}</main>
      <footer>푸터 영역</footer>
    </div>
  );
}

사용할 때는 이렇게 씁니다.

<Layout>
  <h1>홈페이지</h1>
  <p>환영합니다</p>
</Layout>

header와 footer는 항상 고정이고, {children} 자리에 페이지별 콘텐츠가 들어갑니다. 퍼블리싱에서 하던 include 패턴과 원리가 같습니다. 표현 방식만 다를 뿐입니다.

정리

  • children은 컴포넌트 태그 사이에 넣는 내용입니다.
  • 컴포넌트를 껍데기로 만들고, 안에 뭘 넣을지는 사용하는 쪽에서 결정합니다.
  • 이 방식을 **합성(Composition)**이라고 합니다.
  • Layout, Card 같은 재사용 가능한 구조를 만들 때 핵심이 되는 패턴입니다.

children을 이해하면 컴포넌트 설계의 유연성이 크게 올라갑니다. 다음 글에서는 화면이 바뀌는 핵심 원리인 **상태(State)**를 알아보겠습니다.