개발/리액트

리액트 핵심만 훑어보자 #14 합성과 상속

brobro332 2025. 4. 6. 19:47
반응형

📘 『소플의 처음 만난 리액트』를 읽고 정리한 글입니다.

 

합성

  • 여러 개의 컴포넌트를 합쳐서 새로운 컴포넌트를 만드는 것을 말한다.
  • 가령 컴포넌트 A와 컴포넌트 B를 사용해 하나의 페이지를 만들었다고 하면 합성을 사용했다고 볼 수 있다.
  • 아무렇게나 조합하는 것이 아니라 여러 개의 컴포넌트를 어떻게 조합할 것인가에 대한 합성 사용 기법이 존재한다.

 

Containment

  • 하위 컴포넌트를 포함하는 형태의 합성 방법이다.
  • 사이드바나 다이얼로그와 같은 박스 형태의 컴포넌트는 자신의 하위 컴포넌트를 미리 알 수 없다.
  • 예를 들어 두 쇼핑몰 사이트에서 같은 사이드바 컴포넌트를 사용한다고 가정해 보자.
  • 당연히 각 쇼핑몰의 사이드바에 들어갈 메뉴의 개수가 상이할 수 있으므로 하위 컴포넌트를 미리 예측할 수 없다.
  • 이런 경우에는 props에 기본 내장된 children 속성을 사용하는 Containment 기법을 사용하면 된다. 다음 코드와 같다.

 

// 1. Parent
function FancyBorder(props) {
    return (
    	<div className={'FancyBorder FancyBorder-' + props.color}>
        	{props.children}
        </div>
    );
}

// 2. Children
function WelcomeDialog(props) {
    return (
    	<FancyBorder color="blue">
        	<h1 className="Dialog-title">
            	어서오세요
            </h1>
        	<p className="Dialog-message">
            	우리 사이트에 방문하신 것을 환영합니다!
            </p>
        </FancyBorder>
    );
}

 

  • 상기 코드에서는 left, right라는 두 개의 props를 정의하여 그 안에 각각 다른 컴포넌트를 넣어주고 있다.

 

Specialization

  • 범용적인 개념을 구별이 되게 구체화하는 것을 의미한다.
  • 일반적인 객체지향 언어에서는 상속을 이용하여 Specialization을 구현하지만 리액트에서는 합성을 이용하여 구현한다.
// 1. Parent
function Dialog(props) {
    return (
    	<FancyBorder color="blue">
        	<h1 className="Dialog-title">
            	{props.title}
            </h1>
        	<p className="Dialog-message">
            	{props.message}
            </p>
        </FancyBorder>
    );
}

// 2. Children
function WelcomeDialog(props) {
    return (
    	<Dialog
            title="어서오세요"
            message="우리 사이트에 방문하신 것을 환영합니다!"
        />
    );
}
  • 상기 코드에는 Dialog라는 범용적인 컴포넌트와 이 Dialog를 사용하는 WelcomeDialog 컴포넌트가 있다.
  • 제목과 메시지를 어떻게 사용하느냐에 따라서 경고 다이얼로그가 될 수도 있고 인사말 다이얼로그가 될 수도 있다.
  • 이렇듯 Specialization은 범용적으로 쓸 수 있는 컴포넌트를 만들어 놓고 이를 특수화시켜서 컴포넌트를 사용하는 합성 방식이다.

 

Containment + Spectialization

// 1. Parent
function Dialog(props) {
    return (
        <FancyBorder color="blue">
            <h1 className="Dialog-title">
                {props.title}
            </h1>
            <p className="Dialog-message">
                {props.message}
            </p>
            {props.children}
        </FancyBorder>
    );
}

// 2. Children
function SignUpDialog(props) {
    const [nickname, setNickname] = useState('');

    const handleChange = (event) => {
        setNickname(event.target.value);
    }

    const handleSignUp = () => {
        alert(`어서오세요, ${nickname}님!`);
    }

    return (
        <Dialog 
            title="화성 탐사 프로그램"
            message="닉네임을 입력해 주세요">
            <input 
                value={nickname}
                onChange={handleChange} />
            <button onClick={handleSignUp}>
                가입하기 
            </button>
        </Dialog>
    );
}
  • props.children은 Containment에 해당하고, props.title, props.message는 Spacialization에 해당한다.
  • 각 방법을 사용하면 다양하고 복잡한 컴포넌트를 효율적으로 개발할 수 있다.

 

상속

  • 리액트를 개발한 메타는 상속 기반의 컴포넌트 생성 방법을 찾아보려 했으나 그러지 못했다.
  • 결국 복잡한 컴포넌트를 쪼개 여러 개의 컴포넌트로 만들고, 만든 컴포넌트들을 조합하여 새로운 컴포넌트를 만들자는 결론으로 수렴한다.

 

실습 - 합성

// Card.jsx
function Card(props) {
    const { title, backgroundColor, children } = props;

    return (
        <div
            style={{
                margin : 8,
                padding : 8,
                borderRadius : 8,
                boxShadow : '0px 0px 4px grey',
                backgroundColor : backgroundColor || 'white'
            }}
        >
            {title && <h1>{title}</h1>}
            {children}
        </div>
    );
}

export default Card;

// ProfileCard.jsx
function ProfileCard(props) {
    return (
        <Card title="Inje Lee" backgroundColor="#4ea04e">
            <p>안녕하세요,</p>
            <p>저는 리액트를 사용해서 개발하고 있습니다.</p>
        </Card>
    );
}

export default ProfileCard;

// index.js
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <React.StrictMode>
        <ProfileCard />
    </React.StrictMode>
);

reportWebVitals();

 

이미지 출처

 

[React] Component 를 사용하는 기본적인 방법

컴포넌트는 React의 핵심 개념 중 하나이며, 이는 사용자 인터페이스(UI)를 구축하는 기반이다. 컴포넌트를 만들어보자. 우선 여기까지는 순수 JS의 선언 및 정의에 대한 구문이다. 리액트는 컴포

velog.io

 

소플 - soaple.io

소플

www.soaple.io