React 적응기 - 7

김대연·2020년 4월 10일
0

React

목록 보기
7/8

클래스형 컴포넌트

컴포넌트는 클래스형 컴포넌트와 함수형 컴포넌트 두 가지로 나뉘는데, 이 포스트는 클래스형 컴포넌트에 대해 다룹니다.

클래스형 컴포넌트는 이전 포스트에서 설명했던 생명주기(Life cycle) 함수와 컴포넌트 구성 요소를 모두 포함하고 있습니다.

특히 클래스형 컴포넌트는 React.ComponentReact.PureComponent 라는 두 종류의 클래스를 사용하는데 이 두 클래스의 특징과 차이점에 대해 알아보려 합니다.


React.Component

먼저 아래는 우리에게 익숙한 React.Component를 상속한 일반적인 클래스형 컴포넌트의 예시입니다.

import React from 'react';

class ExpComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      sayHello: "Hello World"
    }
  }

  render() {
    return (
      <div>{this.state.sayHello}</div>
    );
  }
}

export default ExpComponent;

constructor에서 props를 전달받기 위해 super(props)를 호출하는 작업을 하고, this.state 에 객체를 할당해 local state 를 리셋해줍니다.

또 이벤트 처리 메서드의 바인딩을 constructort에서 해줄 수도 있습니다. (ES6 Arrow-function 으로 작성도 가능합니다.)

그리고 전 포스트에서 다룬 여러 Life cycle 메서드를 통해 렌더되는 데이터를 관리할 수도 있습니다.

그렇다면 PureComponent를 상속하는 것은 어떠한 차이가 있을까요?

React.PureComponent

React.PureComponentReact.Component 와 비슷하지만 한 가지 차이점이 있습니다. 바로 Life cycle 메서드 중 shouldComponentUpdate() 에 관한 것입니다.

shouldComponentUpdate 와 shallow-compare

React.Component 에서는 shouldComponentUpdate 의 기본값이 true 이기 때문에 매 state 나 props 갱신 시에 렌더링 발생 직전에 호출됩니다.

131 페이지에 실린 예시 코드를 수정하여 사용해보겠습니다.

import React from "react";
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  componentDidUpdate() {
    console.log("MyComponent 새로 고침");
  }

  render() {
    return (
      <div>
        <div>MyComponent</div>
        {this.props.value.map(item => {
          return <span key={item.name}>{item.name} </span>;
        })}
      </div>
    );
  }
}

class MyPureComponent extends React.PureComponent {
  constructor(props) {
    super(props);
  }
  componentDidUpdate() {
    console.log("MyPureComponent 새로 고침");
  }

  render() {
    return (
      <div>
        <div>MyPureComponent</div>
        {this.props.value.map(item => {
          return <span key={item.name}>{item.name} </span>;
        })}
      </div>
    );
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.listValue = [{ name: "Park" }, { name: "Lee" }];
    this.state = { version: 0 };
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    setTimeout(() => {
      this.listValue[0].name = "Justin1";
      this.setState({ version: 1 });
    }, 100);
    setTimeout(() => {
      this.listValue = [{ name: "Justin2" }, { name: "Lee" }];
      this.setState({ version: 2 });
    }, 200);
  }
  render() {
    return (
      <div className="body">
        <MyComponent value={this.listValue} />
        <MyPureComponent value={this.listValue} />
        <button onClick={this.handleClick}>버튼</button>{" "}
      </div>
    );
  }
}

위 예시에서 state 변화가 일어나는 곳은 handleClick() 안에 있는 두 번의 setTimeout() 함수입니다.

React.Component 를 상속한 클래스 컴포넌트라면 각 setState 후에 컴포넌트 업데이트가 일어나 componentDidUpdate() 안의 콘솔이 두 번 출력됩니다.

그런데 React.PureComponent 를 상속한 클래스 컴포넌트는 두 번째 setTimeout() 안의 변화만을 감지하고 업데이트합니다. 왜 그럴까요?

이유는 React.PureComponentshouldComponentUpdate 함수가 shallow-compare, '얕은 비교'를 하도록 재정의 되어있기 때문입니다.

shallow-equal 라이브러리를 사용한 예시(p. 129, 130)를 들어 설명하자면,

import shallowEqual from 'shallow-equal';

const obj = { name: 'park' };
const myList = [1, 2, 3, obj];
const list1 = [1, 2, 3, obj];
const list2 = [1, 2, 3, { name: 'park' }];

myListlist1 은 같은 요소들을 가지고 있지만 각각 새롭게 선언되어 정의된 배열들이기에 일반적인 비교 연산자(Comparison Operator) 로 비교하면 false 를 반환합니다. (shallow/deep copy 의 특징을 생각해보면 object 와 같은 경우는 reference-주소값을 비교합니다. shallow comparison 을 이해하시는데 도움이 될 것 같아 적어보았습니다.)

배열 안의 요소들을 모두 비교하며 검사해볼 수도 있지만 이는 성능에 영향을 미칠 것입니다. 이럴때 shallowEqual 함수를 이용하여 비교하면,

shallowEqaul(myList, list1) //true

true 를 반환하게 됩니다.

마찬가지로 list1list2 를 비교해보면,

shallowEqaul(list1, list2) //false

false 를 반환하게 됩니다.

list2의 마지막 요소는 obj 와 같은 내용을 포함하지만 새로운 객체로서 list2에 존재하고 있습니다.

이렇게 React.PureComponent 는 Life cycle shouldComponentUpdate() 메서드에서 얕은 비교를 하여 데이터의 갱신과 화면 출력을 관리합니다. 특히 불변 변수(Immutable Variable) 을 사용하여 비교 속도를 줄이고 성능을 높일 수도 있습니다.

이번은 클래스형에 대한 내용이었으니 다음 포스트 주제는 함수형 컴포넌트에 관해 작성하려 합니다. 공부중인 책에는 React Hooks 에 대한 내용이 없는 것 같아 Hooks 도 포함하여 작성 예정입니다.


참조

Do it! 리액트 프로그래밍 정석

리액트 공식문서

https://velog.io/@lesh/PureComponent%EC%99%80-componentShouldUpdate-9cjz3nh0v1

0개의 댓글