본문 바로가기
Tech/React

React component

by egas 2021. 5. 29.

Component 란?

 

하드웨어는 각각의 독립된 기능을 가진 모듈들로 만들어진다. 하지만, 소프트웨어는 종속적인 경우가 많고 다른 모듈과의 호환성도 고려하지 않고 개발하는 경우가 많다. 이런 상황에서 재사용의 중요성과 필요성을 위해 나온 패턴컴포넌트 패턴이다.

 

1. 컴포넌트는 독립적인 소프트웨어 모듈이다.

컴포넌트는 독립적인 기능을 수행하는 모듈로서 이후 다른 모듈로 대체 가능하다.

 

2. 컴포넌트는 구현, 명세화, 패키지화 그리고 배포될 수 있어야 한다.

- 소스코드가 아닌 실행코드 기반으로 재사용할 수 있도록 구현(implementation)이 완료되어 있어야 한다.

- 컴포넌트의 용도, 유형, 기술 표준과 인터페이스 등에 대한 정보들에 대해서 명세화(specification)되어 있어야만 한다. 

- 대체 가능한 컴포넌트를 개발하기 위해 표준(standartd)에 맞춰 개발해야 한다.

- 컴포넌트가 개발되어 배포될 때 관련 문서와 코드들이 독립적인 단위로 패키지화되어 있어야 한다.

- 사용자가 필요한 기능만을 패키지 한 컴포넌트를 재사용할 수 있도록 독립적으로 배포(deployment) 가능해야 한다.

 

3. 하나의 컴포넌트는 하나 이상의 클래스/함수로 구성될 수 있다.

컴포넌트 내부에는 하나 이상의 클래스에 대응하는 개개체들이 수행되고 있다.

 

4. 컴포넌트는 인터페이스를 통해서만 접근할 수 있다.

컴포넌트 내부의 정보는 외부로부터 모두 은닉된다. 따라서, 컴포넌트에 접근하기 위해서는 컴포넌트가 정의한 인터페이스를 통해서만 접근 가능하다.

 

 

이런 특징들을 통해 소프트웨어도 하드웨어처럼 조립 기반으로 설계할 수 있다.

 

웹 컴포넌트 규격

웹에도 컴포넌트를 위한 규격들이 있다.

 

  • Shadow DOM : DOM과 스타일을 캡슐화하여 메인으로부터 독립적으로 스크립트와 스타일을 처리할 수 있도록 한다.
  • Custom Elememts : HTML에 새로운 HTML/DOM 요소를 정의할 수 있는 JavaScript API.
  • ES Modules : 이전 규격이었던 HTML Import를 대체하여 나온 규격이며, 자바스크립트로 구현하는 모듈 시스템

 

React: Component-Based

React-Component-Based

React에서 컴포넌트는 개념적으로 props를 input으로 하고 UI가 어떻게 보이는지 정의하는 React.Element Tree를 output으로 하는 함수이다. 컴포넌트 패턴 특성상 컴포넌트끼리의 합성을 이용하여 UI를 재사용할 수 있고 독립적인 단위로 나눌 수 있다. 그래서 컴포넌트 간에는 상속보다는 합성이 권장된다.

 

<button class='button button-blue'>

    <b> OK! </b>

</button>

 

React는 위와 같은 HTML을 일반 객체로 표현한다.

 

{
  type: 'button',
  props: {
    className: 'button button-blue',
    children: {
      type: 'b',
      props: {
        children: 'OK!'
      }
    }
  }
}

 

 

type의 Element를 React 컴포넌트로도 구성할 수 있으며, React 컴포넌트는 함수나 클래스로 생성할 수 있다. 이것이 React의 핵심 아이디어이다.

 

컴포넌트를 설명하는  Element는 DOM node를 나타내는 Element와 마찬가지로 Element이고, 서로 중첩되고 혼합될 수 있다.

 

이러한 특성을 사용하면 다른 요소들의 렌더링 여부를 걱정하지 않고 특정 기능에 집중할 수 있다. 예를 들어, 아래 코드는 children으로 자식 Element를 그대로 넘기기 때문에 특정 기능에 집중할 수 있다. 

 

const DeleteAccount = () => ({
  type: 'div',
  props: {
    children: [{
      type: 'p',
      props: {
        children: 'Are you sure?'
      }
    }, {
      type: DangerButton,
      props: {
        children: 'Yep'
      }
    }, {
      type: Button,
      props: {
        color: 'blue',
        children: 'Cancel'
      }
   }]
});

 

const DangerButton = ({ children }) => ({
  type: Button,
  props: {
    color: 'red',
    children: children
  }
});

 

DangetButton의 Button은 또 다른 컴포넌트이다. 만약, JSX를 선호한다면 DeleteAccount를 다음과 같이 작성할 수 있다.

 

const DeleteAccount = () => (
  <div>
    <p>Are you sure?</p>
    <DangerButton>Yep</DangerButton>
    <Button color='blue'>Cancel</Button>
  </div>
);

 

반환된 Element Tree에는 DOM 노드를 나타내는 Element와 다른 구성 Element를 나타내는 Element가 모두 포함될 수 있다. 이를 통해서 내부 DOM 구조에 의존하지 않고 UI의 독립적인 부분들을 구성할 수 있다.

 

React Component

우리는 이런 Element Tree를 생성하기 위해 컴포넌트를 작성하며, 컴포넌트는 클래스나 함수일 수 있다. 아래는 컴포넌트를 선언하는 세 가지 방법이다.

 

// 1) As a function of props
const Button = ({ children, color }) => ({
  type: 'button',
  props: {
    className: 'button button-' + color,
    children: {
      type: 'b',
      props: {
        children: children
      }
    }
  }
});

// 2) Using the React.createClass() factory
const Button = React.createClass({
  render() {
    const { children, color } = this.props;
    return {
      type: 'button',
      props: {
        className: 'button button-' + color,
        children: {
          type: 'b',
          props: {
            children: children
          }
        }
      }
    };
  }
});

// 3) As an ES6 class descending from React.Component
class Button extends React.Component {
  render() {
    const { children, color } = this.props;
    return {
      type: 'button',
      props: {
        className: 'button button-' + color,
        children: {
          type: 'b',
          props: {
            children: children
          }
        }
      }
    };
  }
}

 

컴포넌트가 클래스로 정의되면 함수 컴포넌트보다 조금 더 강력하다. 해당 DOM노드가 생성, 삭제될 때 일부 시점에서 사용자 정의 로직을 수행할 수 있다.

 

함수 컴포넌트는 덜 강력하지만 더 간단하며 클래스 컴포넌트의 단일 render() 메서드와 같이 동작한다. 클래스에서만 사용할 수 있는 기능이 필요하지 않은 경우에는 함수 컴포넌트를 사용하는 것이 좋다.

 

함수나 클래스는 근본적으로 React의 컴포넌트의 한 요소이다. 모두 props를 input으로 받고, Elements들을 output으로 반환한다.

 

Top-Down Reconciliation

React는 아래와 같이 Element를 DOM 노드에 연결한다.

ReactDOM.render({
  type: Form,
  props: {
    isSubmitted: false,
    buttonText: 'OK!'
  }
}, document.getElementById('root'));

 

React는 Form 컴포넌트에게 어떤 Elements Tree를 반환하는지 질의하며 점진적으로 세분화해나간다.

 

// React: You told me this...
{
  type: Form,
  props: {
    isSubmitted: false,
    buttonText: 'OK!'
  }
}

// React: ...And Form told me this...
{
  type: Button,
  props: {
    children: 'OK!',
    color: 'blue'
  }
}

// React: ...and Button told me this! I guess I'm done.
{
  type: 'button',
  props: {
    className: 'button button-blue',
    children: {
      type: 'b',
      props: {
        children: 'OK!'
      }
    }
  }
}

 

이 과정은 React에서 재조정(reconciliation)라고 불리는 과정의 일부분이다. Reconciliation은 ReactDOM.render()이나 setState()을 호출할 때, 발생한다.

 

다음은 React 홈페이지 가장 상단에 있는 부분이다.

React-Component-Based

이제 문장의 의미가 이해가된다. React는 DOM관련 javascript 함수들을 컴포넌트로 캡슐화시켰기 때문에 우리가 직접 다루지 않을 수 있고, DOM과는 별개로 상태를 관리하며, 성능을 개선할 수 있다.

 

참고 자료

 

React Components, Elements, and Instances – React Blog

The difference between components, their instances, and elements confuses many React beginners. Why are there three different terms to refer to something that is painted on screen? Managing the Instances If you’re new to React, you probably only worked w

reactjs.org

 

 

React의 기본, 컴포넌트를 알아보자

모두 알지만 잘 알지는 못하는 컴포넌트

medium.com

 

728x90

'Tech > React' 카테고리의 다른 글

useEffect 정리  (0) 2021.07.22
[Typescript] CRA에서 http-proxy-middleware 사용법  (0) 2021.07.14
ReactNode vs ReactElement vs JSX.Element  (0) 2021.07.07
react 리뷰 정리  (0) 2021.06.15
선언형 프로그래밍과 명령형 프로그래밍  (0) 2021.05.11

댓글