합성 vs 상속

Yeom Jae Seon·2021년 2월 10일
0

React공식문서 공부

목록 보기
10/11
post-thumbnail

합성과 상속


결론부터 말하면 React에서는 강력한 합성모델을 가지고 있으며 상속으로 코드를 재사용하기 보단 합성을 이용해서 컴포넌트간에 코드를 재사용하는것이 좋다.
(합성이란 컴포넌트 합성 컴포넌트편에서 컴포넌트는 자신의 출력에 다른 컴포넌트를 참조할수 있다로 배웠고 지금까지 많은 예제를 하며 경험해왔다.)

합성을 많이 해봤지만 다시한번 하면서 경험해보자.

  • React에서는 상속보단 컴포넌트 합성을 이용해서 컴포넌트간 코드를 재사용하는 것이 좋다. React에선 강력한 합성모델이 존재하기 때문이다.
  • 합성이란 컴포넌트의 출력에 다른 컴포넌트를 참조할수 있는 것을 말한다.

컴포넌트에서 다른 컴포넌트를 담기(컴포넌트 합성)


어떠한 컴포넌트는 어떤 자식엘리먼트가 올지 예상할수 없는 경우가 많다. 구체적인 컴포넌트보단 일반적인 컴포넌트가 그런경우가 많다. 예를들면 Header컴포넌트는 안에 어떤 리스트가 올지 모르겠다.

이러한 경우 props children을 통해서 자식 엘리먼트를 그대로 출력하는 것이 좋다.

(우리는 React는 단방향 데이터 흐름이라는 것을 알고있다.
이는 컴포넌트간 props를 통해서 데이터가 전달되기 때문이란 것도 알고 있다.
그리고 props는 컴포넌트에 전달된 속성children이 담겨있는 객체라는 것도 알고있다.)

단순히 전달되는 자식엘리먼트를 그대로 받아서 출력할 때와 자식 엘리먼트를 다양하게, 여러개의 구멍으로 받는 경우가 존재한다.

먼저

  1. props children으로 컴포넌트(리액트 엘리먼트)를 전달하기
    이 경우는 단순히 자식 리액트 엘리먼트(혹은 컴포넌트)를 그대로 전달만 할때 사용하는 것이 좋다.
const FoodIntroduction = (props) => {
  return <div>{props.children}</div>;
};

const BananaIntroduction = () => {
  return (
    <FoodIntroduction>
      <div>
        <h1>바나나</h1>
        <p>껍질은 노랗고 속은 하얗습니다.</p>
      </div>
    </FoodIntroduction>
  );
};

BananaIntroduction컴포넌트가 출력하는 곳에서 FoodIntroduction컴포넌트를 참조하는 컴포넌트 합성이다.

이 경우 단순히 내용만 FoodIntroduction에게 그대로 전달하기 때문에 FoodIntroduction에선 children props로 받는 것이 좋다.

  1. props속성을 통해서 컴포넌트를 다른컴포넌트로 전달하기(여기선 컴포넌트를 전달하는데 컴포넌트가 리액트 엘리먼트를 리턴하므로 위 예제와 다른점은 props 속성으로 리액트 엘리먼트를 전달하는 점밖에 없겠습니다.)
    위의 경우에선 props.children으로 단 하나의 구멍으로 밖에 전달이 안된다. 그치만 props 속성을 이용하면 여러 구멍을통해 다양하게 컴포넌트를 다른컴포넌트로 전달할수 있다.
    그리고 아래 예시에선 단순히 출력하는 기능밖에 하지 않는 즉, props children과 비슷해보이지만 그렇지 않은 경우가 props 속성을 이용하는 경우이다.
const FoodIntroduction = (props) => {
  return (
    <div>
      <div>{<Apple />}</div>
      <div>{<Banana />}</div>
    </div>
  );
};

const Apple = () => <h1>사과</h1>;

const Banana = () => <h1>바나나</h1>;

const Food = () => {
  return <FoodIntroduction apple={<Apple />} Banana={<Banana />} />;
};

이런식으로 컴포넌트를 다른 컴포넌트로 전달하며(= 컴포넌트 출력에 다른컴포넌트를 참조하는 방법 = 컴포넌트 합성) props를 사용할수 있고 props는 오브젝트이고 이 props 오브젝트 중 children을 이용하거나, props 속성을 이용해 리액트 엘리먼트를 전달하수 있다.
리액트 엘리먼트는 객체이므로 가능하다. 너무 이상하다, 너무 이질감든다고 생각할필요없이 JS의 오브젝트(객체)를 props로 넘긴다고 생각하자!

  • 컴포넌트 합성중 props를 통해 React Element를 전달할수 있다.
  • props children을 사용하는 경우는 전달된 데이터를 그대로 출력하는 경우이고 props 속성을 이용하는 경우는 여러개의 입력 구멍이 필요한 경우이다(props children은 입력구멍이 하나밖에 안되닌까.).

일반적인 컴포넌트의 구체적인 경우 고려하기


일반적인 컴포넌트의 구체적인 컴포넌트를 고려할 때가 종종있다.
예를들면 음식 소개 컴포넌트인 일반적인 컴포넌트에서 치킨 소개하는 구체적인 컴포넌트인 경우이다.

이럴때 컴포넌트 합성을 이용한다. 즉, 구체적인 컴포넌트가 출력하는 부분에 일반적인 컴포넌트를 참조(합성)하고 전달되는 구체적인 데이터는 props로 전달되면된다. 이게 입력되는 구멍이 하나면 props.children이고 아니면 props속성이겠다. (참고로 props는 읽기전요! props받는 컴포넌트는 순수함수! 함수라면)

(이부분은 직접 만들어보거나 코드를 보면 바로이해할수 있는 부분.!)

const FoodIntroduction = (props) => {
  return (
    <div>
      <h1>{props.name}</h1>
      <p>{props.description}</p>
    </div>
  );
};

const Chicken = () => {
  return <FoodIntroduction name="치킨" description="닭을 튀긴 요리입니다." />;
};

일반적인 FoodIntroduction컴포넌트를 구체적인 Chicken컴포넌트에서 합성 시킨거고 props로 구체적인 정보를 전달한 것이다.

이렇게 컴포넌트 합성을 이용해서 코드를 재사용할수있다.

피자를 소개한다하면

const Pizza = () => {
  return <FoodIntroduction name="피자" description="치즈랑 빵입니다." />;
};

이렇게 간단하게 피자 컴포넌트만 만들면 쉽게 FoodIntroduction인 일반적인 컴포넌트의 코드를 재사용할수 있다.

  • 일반적인 컴포넌트의 특수한 경우엔 컴포넌트 합성을 이용해 props로 구체적인 정보만 넘기면 코드를 재사용할수 있다.

결론


이렇게 React에서는 합성을 통해서 컴포넌트를 계층구조로 작성하고 그에 맞게 컴포넌트의 코드도 재사용이 가능하다.

위에서 본거와 같이 props로 전달되는 데이터는 다른 컴포넌트(리액트 엘리먼트 === 객체)일수도 있고 primitive type일수도 있고 state끌어올리기에서 사용한 함수 일수도 있다.
즉, 어떠한 녀석도 props로 받을수 있고 이 props와 합성을 통해 코드의 유연성을 제공한다.

참고로 React는 UI라이브러리이다. 즉 View에 해당되기 때문에 UI외의 기능에 대해선 다른 모듈로 만들어 UI부분과 분리 하는 것이 좋다.

  • 컴포넌트 합성을 사용할 때 props를 통해서 컴포넌트의 재사용성을 높일수 있다.
  • props에 올수 있는 값으로는 어떠한 것도 올 수가 있다.
  • React에서는 상속보단 합성과 props를 통해서 컴포넌트간의 유연성과 코드의 재사용성을 높일수 있다.
  • React는 View layer이므로 UI이외의 로직은 다른 JS모듈로 관리하는 것이 적절하다

위 내용은 공식문서를 보면서 나름대로 공부한 내용을 정리한 문서입니다.
https://ko.reactjs.org/docs/composition-vs-inheritance.html

0개의 댓글