합성(Composition) vs 상속(Inheritance)

5o_hyun·2022년 12월 27일
0
post-thumbnail

합성(Composition)

여러개의 컴포넌트들을 조합하는것
조합방법에 따라 Composition 사용기법이 나뉜다.

1. Containment

하위 컴포넌트를 포함하는 형태의 합성방법
범용적인 ‘박스’ 역할을 하는 Sidebar 혹은 Dialog와 같은 컴포넌트는, 자신의 하위 컴포넌트를 미리 알 수 없다.
이러한 컴포넌트에서는 children이라는 prop을 사용해서 조합한다.

function FancyBorder(props) {
  return (
    <div className={'FancyBorder FancyBorder-' + props.color}>
      {props.children}
    </div>
  );
}
function WelcomeDialog() {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        Welcome
      </h1>
      <p className="Dialog-message">
        Thank you for visiting our spacecraft!
      </p>
    </FancyBorder>
  );
}

FancyBorder컴포넌트 안에 있는 모든 jsx태그는 children으로 전달되어 결과적으로 파란색 테두리로 모두 감싸지는 결과가 나온다.

여러개의 chidren집합이 필요한 경우는 어떻게 할까 ?
직접 별도로 props를 정의해서 각각 원하는 컴포넌트를 넣어주면된다.

/* 
	SplitPane-left, SplitPane-right는 props로 받아서 
	각각 왼쪽 오른쪽에 다른것을 나타낸다.
*/
function SplitPane(props) {
  return (
    <div className="SplitPane">
      <div className="SplitPane-left">
        {props.left}
      </div>
      <div className="SplitPane-right">
        {props.right}
      </div>
    </div>
  );
}

function App() {
  return (
    <SplitPane
      left={
        <Contacts />
      }
      right={
        <Chat />
      } />
  );
}

2. Specialization 특수화

WelcomeDialog는 Dialog의 특수한 경우라고 할 수 있다.

Dialog는 모든종류의 Dialog를 포함하므로 범용적인 의미고,
WelcomeDialog는 누군가를 반기기위한 범용적인 개념이아니라 좀 더 구체적인 의미이다.

즉, 범용적으로 쓸 수 있는 컴포넌트를 만들어놓고, 이를 특수화시켜서 컴포넌트를 사용하는 합성방법이다.

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

function WelcomeDialog() {
  return (
    <Dialog
      title="어서오세요!"
      message="우리 사이트에 방문을 해주셔서 감사합니다." />
  );
}

3. Containment 와 Specialization 같이 사용하기

Containment를 사용하기위해 props.chidren을 사용하고, Specialization를 사용하기위해 직접 정의한 props를 사용한다.

function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
      {props.children} 
      /* 
      	1. Containment를 사용하기위해 props.children추가.
      	이로인해 하위 컴포넌트가 Dialog 하단에 렌더링된다.
      */
    </FancyBorder>
  );
}

class SignUpDialog extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.handleSignUp = this.handleSignUp.bind(this);
    this.state = {login: ''};
  }

  render() {
    return (
      /* 
      	2. specialization을 위한 props인 title,message에 값을 넣어주고있으며 
        
        사용자로부터 닉네임을 입력받고 가입을 유도하기위해 input,button테그가있다.
        이 두개의 태그는 모두 props.children으로 전달되어 dialog에 표시된다. 
        => Containment
      */ 
      <Dialog title="Mars Exploration Program"
              message="How should we refer to you?">
        <input value={this.state.login}
               onChange={this.handleChange} />
        <button onClick={this.handleSignUp}>
          Sign Me Up!
        </button>
      </Dialog>
    );
  }

  handleChange(e) {
    this.setState({login: e.target.value});
  }

  handleSignUp() {
    alert(`Welcome aboard, ${this.state.login}!`);
  }
}

상속(Inheritance)

다른 컴포넌트로부터 상속을 받아서 새로운 컴포넌트를 만드는것.
그러나, 합성보다 좋은점을 찾지 못해서 추천하지않는다. 상속보다는 합성을 이용하여 컴포넌트를 만드는것을 추천한다.

복잡한 컴포넌트를 쪼개서 여러개의 컴포넌트로 만들고, 만든 컴포넌트들을 조합해서 새로운 컴포넌트를 만들자!

profile
학생 점심 좀 차려

0개의 댓글