반응형
📘 『소플의 처음 만난 리액트』를 읽고 정리한 글입니다.
합성
- 여러 개의 컴포넌트를 합쳐서 새로운 컴포넌트를 만드는 것을 말한다.
- 가령 컴포넌트 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
'개발 > 리액트' 카테고리의 다른 글
[完] 리액트 핵심만 훑어보자 #16 Styled-Component (3) | 2025.04.06 |
---|---|
리액트 핵심만 훑어보자 #15 컨텍스트 (1) | 2025.04.06 |
리액트 핵심만 훑어보자 #13 컴포넌트 간 상태 공유 (1) | 2025.03.11 |
리액트 핵심만 훑어보자 #12 폼 (1) | 2025.03.09 |
리액트 핵심만 훑어보자 #11 리스트와 키 (1) | 2025.03.08 |