본문 바로가기
Front-end/React

리액트 합성(Composition)이란?

by mooyou 2025. 2. 12.
728x90
300x250
SMALL

리액트 합성은 컴포넌트를 조합하여 더 큰 컴포넌트를 구성하는 방식이다.

즉 여러 개의 컴포넌트를 합쳐서 새로운 컴포넌트를 만드는 것이라고 할 수 있다.

이를 통해 재사용성과 유연성을 높이며, 상속보다 구성 철학을 따른다.

합성은 컴포넌트를 다른 컴포넌트의 자식이나 속성으로 전달하여 구조를 구성하는 것을 의미한다.


 

리액트 합성의 주요 패턴

1. 자식 컴포넌트를 사용하는 합성

컴포넌트 내부에서 props.children을 통해 하위 컴포넌트를 포함하는 방식

이 패턴은 레이아웃 컴포넌트(예: 카드, 모달, 컨테이너 등)에서 자주 사용된다.

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

// Card 컴포넌트 사용 예시
function App() {
    return (
        <Card>
            <h1>안녕하세요!</h1>
            <p>리액트를 배우는 중입니다.</p>
        </Card>
    );
}

 

  • Card컴포넌트는 내부적으로 props.children을 사용하여 자식요소(컴포넌트)를 렌더링하는 역할을 한다.
  • <Card> 안에 <h1>과 <p>가 있으므로, 이 요소들이 props.children으로 전달 됨.

최종 렌더링 결과

<div class="card">
    <h1>안녕하세요!</h1>
    <p>리액트를 배우는 중입니다.</p>
</div>

 

Card 컴포넌트는 틀(Wrapper)역할을 하고, 그 안의 내용(children)을 감싸서 렌더링한다.

이렇게 여러 컴포넌트를 조립해서 하나의 컴포넌트로 만든다.


 

2. 특수화(Specialization)

컴포넌트의 일반적인 형태를 기반으로 특수한 컴포넌트를 구현할 때 사용한다.

부모 컴포넌트가 공통 로직을 제공하고, 자식 컴포넌트가 세부사항을 결정한다.

function Dialog({ title, message, children }) {
    return (
        <div className="dialog">
            <h3>{title}</h3>
            <p>{message}</p>
            {children}
        </div>
    );
}

function WelcomeDialog() {
    return (
        <Dialog title="환영합니다!" message="리액트를 즐기세요!">
            <button>확인</button>
        </Dialog>
    );
}
  • <WelcomeDialog>실행 → <Dialog> 컴포넌트 호출됨
  • <Dialog>에 title="환영합니다!", message="리액트를 즐기세요!", children=<button>확인</button>을 넘겨줌

최종 렌더링 결과

<div class="dialog">
    <h3>환영합니다!</h3>
    <p>리액트를 즐기세요!</p>
    <button>확인</button>
</div>

 

  • <Dialog>는 모달 같은 공통 UI틀 제공
  • <WelcomeDialog>는 특정내용(title, message, children)을 넣어서 Dialog를 확장
  • 즉, 재사용성을 높이기 위해 컴포넌트를 합성함

3. 컨테이너와 프레젠테이션 컴포넌트 분리

데이터 처리와 UI 렌더링 역할을 분리하는 방식으로, 구조화된 재사용성을 높인다.

function List({ items, renderItem }) {
    return <ul>{items.map(renderItem)}</ul>;
}

function App() {
    const fruits = ["사과", "바나나", "체리"];
    return (
        <List
            items={fruits}
            renderItem={(item) => <li key={item}>{item}</li>}
        />
    );
}

 

  • fruits = ["사과", "바나나", "체리" ] 배열이 List에 props.items로 전달됨.
  • renderItem={(item) => <li key={item}>{item}</li>} 이라는 콜백 함수를 넘겨줌.
  • List 컴포넌트에서 items.map(renderItem)을 실행 → "사과", "바나나", "체리" 각각에 대해 renderItem 실행됨

최종 렌더링 결과

<ul>
    <li>사과</li>
    <li>바나나</li>
    <li>체리</li>
</ul>

 

  • List는 데이터 배열을 받아서 원하는 방식으로 렌더링할 수 있도록 유연한 구조를 제공
  • 함수를 props로 전달해서 동적으로 원하는 형태의 리스트를 만들 수 있다.
  • 이렇게 하면 컴포넌트의 재사용성이 극대화된다. (다른 곳에서 List를 사용할 때 renderItem만 바꿔주면 됨)
728x90
반응형
LIST

댓글