웹 프론트엔드 개발에 도전하다 2편

Spes Lim·2020년 8월 2일
2

web-frontend

목록 보기
2/3

지난 2 주간 React 라이브러리를 공부하면서 리액트 컴포넌트의 라이프사이클과 메서드의 동작방식, 그리고 api를 사용해 클라이언트와 데이터를 연동시키는 작업을 했습니다. 이번 편에서는 리액트 컴포넌트의 라이프사이클에 대해 자세히 풀어보려고 합니다.

React component의 LifeCycle method

리액트의 라이프사이클은 mount, update, unmount로 총 3가지 입니다. 이 3가지 요소들은 다음과 같은 원리로 동작 합니다.

  • mount : Component 함수가 실행되고 결과물로 나온 Element(객체)들이 virtual DOM에 삽입되고 실제 DOM에 업데이트 요청을 하는 과정입니다.
import React, { Component } from 'react';

class LifeCycleExample extends Component {
...

이 과정에서 호출되는 메서드는 차례로 다음과 같습니다.

Mount

1.1 constructor

컴포넌트를 새로 만들 때마다 호출되는 클래스 생성자 메서드 입니다.
하지만, 메서드를 따로 바인딩하거나 state를 초기화하는 작업이 없다면
호출할 필요는 없습니다. 대개 아래와 같은 경우에서 constructor가 사용됩니다.

class LifeCycleExample extends Component {
  constructor(props) {
    super(props);
    
    this.state = {
      isExample = true,
      isUpdate = null
    };
    this.handleClick = this.handleClick.bind(this);
  }

React.Component를 상속한 컴포넌트의 생성자를 구현할 때는
반드시 생성자 메서드 아래에 super(props); 구문을 선언해야 합니다.
자바스크립트에서 super()는 부모클래스 생성자의 참조 입니다. 생성자 메서드에서 super()를 호출하기 전까지 this 객체를 사용할 수가 없습니다.
그 이유는, 부모클래스의 객체의 속성이 변경 되었을 경우 그대로 this 객체를 사용하게 되면 변경사항까지 업데이트 되기 때문입니다.

바로 이 점은 제가 1편에서도 앞서 서술 했듯이, function componentclass component가 동작이 어떻게 달라지느냐의 관계와도 같은 원인을 공유하고 있습니다.

1.1.1 constructor 사용시 주의 사항

공식 문서에서는 생성자 메서드 내부에 setState()을 호출 하면 안된다고 나와 있습니다. 왜 그럴까요?

  • setState() : component의 state 객체를 업데이트 시킨다. state가 변경되면 component는 리렌더링 된다.

초기화를 시켜줘야 할 객체를 업데이트 시키고, component가 리렌더링 된다면 정보를 제대로 받아서 mount 하기가 어려워 질 것입니다. 그런 이유로 React.Component에서는 constructor() 내부에 setState() 사용을 금지 하고 있습니다.

1.2 getDerivedStateFromProps

props에 있는 값을 state에 넣을 때 사용하는 메서드 입니다.
component가 mount 될 때와 update 될 때 호출 됩니다.
물론 mount 과정에서 뒤에 서술할 render() 함수가 호출 되기 이전에 호출 됩니다.

static getDerivedStateFromProps(nextProps, prevState) {
  if(nextProps.value !== prevState.value) {
    return { value: nextProps.value }; // 다음 props값으로state 변경한 뒤 render() 호출 준비
  }
  return null;
}

1.3 render()

이 메서드는 UI를 렌더링 하는 함수 입니다. 여기서 리렌더링 작업이 진행되는데, 이 render() 함수는 ReactDOM의 참조 입니다. ReactDOM은 UI를 실제로 브라우저에 렌더링 할 때 쓰이는 모듈 입니다.
React의 Element는 불변객체 입니다. Element를 선언 하면 그 이후에 해당 Element의 자식이나 속성을 제어할 수 없습니다. 따라서 업데이트 할 수 있는 방법은 새로운 Element를 생성해서 ReactDOM.render()로 업데이트 사항을 반영해야 하는 것입니다. 그렇기 때문에 이 render() 함수 내에서는 this.propsthis.state에 접근하여 React Element를 반환 합니다.

1.4 componentDidMount

render() 함수 내에서는 사용할 수 없는 규칙이 몇 가지 있습니다.

  • (별도의 event가 없는 한) setState()를 사용할 수 없습니다.
  • 브라우저의 DOM에 접근할 수 없습니다.
  • state에 변화를 줄 수 없습니다.

componentDidMount 메서드는 첫 렌더링을 다 마친후에 자바스크립트의 Event나 브라우저의 DOM 정보를 가져오는 메서드 입니다. 비동기 작업도 이 메서드 안에서 이루어 집니다.

Update

이렇게, 업데이트 직전까지의 상황을 우리는 공부했습니다. React Component는 다음과 같은 경우에 업데이트를 실행합니다.

  1. props 가 바뀌는 상황
  2. state 가 바뀌는 경우
  3. 부모 컴포넌트 가 리렌더링 될 때
  4. this.forceupdate 로 강제로 렌더링을 트리거 하는 경우

이 중에서 4번을 제외한 나머지 경우에 대해 메서드가 어떻게 호출되는지 순차적으로 알아봅니다.

2.1 getDerivedStateFromProps 호출

위에서 서술 했듯이, mount 과정에도 호출 되지만, 업데이트 시작 전에 해당 메서드가 호출됩니다. props 의 변화에 따라서 state 값에도 변화가 필요한 경우 해당 메서드를 호출해서 코드를 수정합니다.

2.2 shouldComponentUpdate 호출

컴포넌트가 리렌더링을 할 것인지 결정하는 메서드 입니다. 이 메서드에서는 오직 boolean 값을 반환 해야 하는 규칙이 있습니다.

2.3 render() 호출

여기서 컴포넌트의 리렌더링이 이루어 집니다.

2.4 getSnapshotBeforeUpdate 호출

컴포넌트의 변화를 브라우저의 DOM에 반영하기 직전에 호출하는 메서드 입니다. 이 메서드의 목적은 업데이트 하기 직전의 값을 참조해야 할 일이 있을 때 활용 됩니다.

2.5 componentDidUpdate 호출

componentDidUpdate(prevProps, prevState, snapshot) {...}

여기서 세 번째 파라미터인 snapshot이 조금 익숙하게 느껴집니다. 그렇습니다. getSnapshotBeforeUpdate 메서드에서 반환하는 값을 snapshot 파라미터가 받습니다.

componentDidUpdate 메서드는 리렌더링이 완료 된 후에 실행됩니다.
여기서는 prevProps 또는 prevState 파라미터를 사용해서 컴포넌트가 업데이트 이전에 유지했던 데이터로 접근이 가능합니다. 물론, 업데이트가 끝난 상황이므로 DOM 처리가 가능합니다.

Unmount

컴포넌트를 브라우저의 DOM에서 제거하는 것을 말합니다.
만일, 한 컴포넌트가 지속적인 에러를 발생시키고 있다면 해당 컴포넌트를 지워야 할 경우가 생길 수 있습니다. 이 때, componentWillUnmount 메서드를 사용해서 컴포넌트를 제거합니다.

여기까지, React Component에 대한 기본 라이프사이클 개념을 알아봤습니다. 다음 편에는 이 라이프사이클 대로 페이지가 어떻게 렌더링이 되고, 앱을 만드는 지 그 동작을 서술하도록 하겠습니다.

profile
Software Developer

0개의 댓글