React Life Cycle ?

김진현·2023년 10월 2일
0

React

목록 보기
1/2

(React Life Cycle) 리액트 생명주기 이해를 위해선 간단한 브라우저의 동작방식과 Virtual DOM에 대한 지식이 있어야 합니다.

Browser WorkFlow

간단히 순서만 정리해보겠습니다.

  1. 브라우저에 렌더링 엔진이 HTML을 파싱하여 DOM노드로 이루어진 TREE가 생성됩니다.

  2. CSS파일이나 HTML에 인라인으로 작성된 스타일코드를 파싱하여 CSS DOM 을 구성합니다.

    이렇게 만들어진 DOM TREE와 CSS DOM을 결합하여 렌더 트리를 생성합니다.

    (render tree : 문서의 시각적 구조)

  3. 각 노드들의 스크린에서의 좌표에 따라 위치를 결정합니다. position, size 등이 여기서 계산됨 (reflow)

  4. 구성된 레이아웃을 실제 화면에 그립니다(repaint)

여기서 문제는 어떠한 interaction에 DOM변화가 생기면 render tree가 그때마다 재 생성이 된다는 점입니다.

(생각만해도 비효율적이죠,,)

변화가 발생하면 모든 요소들의 스타일을 다시 계산하고 레이아웃, reflow과정을 거쳐 다시 repaint하는 과정까지 반복이 됩니다. (불필요한 과정의 반복)

최근 많이 사용하는 SPA(싱글 페이지 어플리케이션)은 DOM조작이 많이 발생합니다. 전체 페이지를 서버에서 매번 보내주는 것이 아니라 브라우저 단에서 자바스크립트가 관리하기 때문에 DOM 조작을 효율적으로 할 수 있도록 최적화가 필요했습니다.

이때 VIRTUAL DOM 이 등장하였습니다.

VIRTUAL DOM

VIRTUAL DOM이란 복사본이라고 표현하기도 하며, 가상의 레이어 입니다. VIRTUAL DOM은 메모리상에 UI 관련된 표현해야하는 핵심 정보들을 띄워놓고, REACT와 같은 라이브러리가 실제 DOM이랑 VIRTUAL DOM이랑 싱크를 맞춰준다고 생각하면 됩니다.

실제 DOM object와 같은 속성을 지니고 있으나, 실제 DOM이 가지고있는 API는 가지고 있지 않습니다.

데이터가 변경되면 전체 UI는 VIRTUAL DOM에 렌더링됩니다. 그리고 VIRTUAL DOM에 있던 내용과 업데이트 후의 내용을 비교하여 바뀐 부분만 실제 DOM에 적용시킵니다.

-> 전체 DOM을 바꾸지 않아도 필요한 업데이트 적용 가능함

VIRTUAL DOM에 적용하는 변경사항들은 DOM에 바로 반영되지않고, 변경사항들을 모아두었다가 한꺼번에 DOM한테 보냅니다. -> 더빠르게, 연산비용 적음

React Life Cycle 이란?

WHY?

리액트 생명주기를 알아야 주기에 따라 어떠한 작업들을 수행해주어야 불필요한 리렌더링 등을 사전에 방지 할 수 있습니다.

React Element -> DOM Element?

하나의 화면 표시를 위해 여러 개의 React Element가 tree형태를 이룹니다. 데이터 변경에 의한 화면 업데이트는 렌더단계 -> 커밋단계 를 거치게 됩니다.

Render Phase : 실제 돔에 반영할 변경사항들을 파악하는 단계입니다. (리액트 렌더링할때마다 가상돔을 만듬)

Commit Phase : 파악된 변경사항들을 실제 돔에 반영하는 단계입니다. (변경사항 있으면 실제 돔에 반영)

생명 주기 메서드

리액트는 컴포넌트 단위로 개발을 진행합니다. 이때 각 컴포넌트들은 생명주기를 가지게 됩니다.

생명주기 : 생성(Mounting) -> 업데이트(Updating) -> 제거(Unmounting)

클래스 컴포넌트의 경우 Life Cycle 메서드를 활용하고

함수 컴포넌트의 경우 Hook을 사용합니다.

라이프 사이클 과정에서 여러가지 메서드들이 존재하며 단계별로 간단히 나타내 보았습니다.

1. 마운트 단계 (초기화 단계, Mount)

최초에 컴포넌트 객체가 생성 될 때 한번 수행합니다.

  • constructor : react 컴포넌트의 constructor는 해당 컴포넌트가 마운트 되기 전에 호출됩니다.

    this.state 에 객체를 할당하여 지역 state 초기화

    인스턴스에 이벤트 처리 메서드를 바인딩

class MyComponent extends React.Component {
  constructor(props) {
    super(props); // 필요한 경우, props를 전달
    // 여기서 컴포넌트의 초기화 작업을 수행할 수 있습니다.
    this.state = {counter : 0}
  }
  // 나머지 컴포넌트 코드
}
  • getDerivedStateFromProps : props로 받아온 것을 state에 넣을 때 사용되는 메서드입니다. 컴포넌트가 처음 렌더링 되기 전에 호출되며, 리렌더링 되기 전에도 항상 실행됩니다.
 // getDerivedStateFromProps 메서드 정의
  static getDerivedStateFromProps(nextProps, prevState) {
    // props로 받은 값을 기반으로 새로운 state를 반환
    if (nextProps.someProp !== prevState.derivedState) {
      return {
        derivedState: nextProps.someProp
      };
    }

    // state를 변경할 필요가 없으면 null을 반환
    return null;
  }

앞에 static이 붙습니다. 이 안에서는 this를 조회할 수 없습니다.

특정 객체를 return하게 되면 해당 객체 안에 있는 내용들이 컴포넌트의 state로 설정이 됩니다.

null 을 반환하면 아무 일도 발생하지 않습니다.

  • render : 컴포넌트를 렌더링 하는 메서드입니다.

  • componentDidMount : 컴포넌트의 첫 렌더링을 마친 후 호출되는 메서드입니다. 이 메서드가 호출되는 시점에선 화면에 컴포넌트가 출력된 상태이며 axios, fetch 등을 사용해 필요한 데이터 요청 등의 작업을 진행합니다.

2. 업데이트 단계 (Update)

초기화 단계와 소멸 단계 사이에서 반복해서 수행됩니다. 컴포넌트 상태 값 or 속성 값이 변경되면 호출됩니다.

props, state 값 바뀔때, 부모컴포넌트가 re-render 될때, this.forceUpdate()로 강제로 렌더링 트리거 시

  • getDerivedStateFromProps : 마운트때와 동일한 메서드 입니다.

  • shouldComponentUpdate : 컴포넌트가 리렌더링을 할지 말지를 결정하는 메서드입니다. 주로 최적화 할 때 사용하는 메서드이며 useMemo와 비슷한 역할을 합니다.

class SampleComponent extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    const { age } = this.state;
    return age !== nextState.age;
  }
}

boolean값을 반환합니다. (true면 render, false면 멈춤), true가 발생하면 render 메서드가 호출되고 가상 돔 수준에서 변경된 내용이 있는지 확인합니다.

위의 예시코드를 보면 age 상태값이 변경된 경우에만 true를 반환하므로 나머지 상태값들이 변경되더라도 렌더링 되지 않습니다. 이 메서드를 사용안하면 실제돔이 변경되지 않은 상황에서도 가상돔과 비교하게됨.

  • render : 컴포넌트를 렌더링 하는 메서드입니다.

  • getSnapshotBeforeUpdate() : 컴포넌트가 업데이트 되기 전에 호출되는 메서드입니다. render가 실행된 후 업데이트 발생하기 직전에 실행됩니다.

  • 컴포넌트에 변화가 일어나기 직전의 DOM상태를 캡쳐하여 업데이트 된 DOM과 변경된 부분을 파악하는데 사용합니다.

  • componentDidUpdate : 컴포넌트 업데이트 작업이 끝난 후 호출되는 메서드입니다. 리렌더링을 마치고 화면에 업데이트가 모두 반영이됩니다.

3. 제거단계 (Unmount)

  • componentWillUnmount() : 컴포넌트가 마운트 해제 되어 제거되기 직전에 호출됩니다. 주로 DOM 이벤트 리스너들을 해제하거나 끝나지 않은 네트워크 요청 해제 등의 작업을 처리합니다.
  • componentDidMount 메서드가 호출되면 componentWillUnmount 메서드도 호출되는 것이 보장된다고 합니다..

  • 그래서 componentDidMount에서 구독하고 componentWillUnmount에서 해제하는 코드가 주로 사용된다고 합니다.

예외

getDerivedStateFromError(error), componentDidcatch(error, info) 메서드 들은 생명 주기 메서드에서 발생한 예외를 처리하는 메서드입니다.

여지껏 클래스컴포넌트에서 활용할 수 있는 LifeCycle API였습니다.

그렇다면 함수 컴포넌트는??​

React Hook

함수 컴포넌트에서 React state와 라이프 사이클 기능을 연동할 수 있게 해주는 함수입니다.

클래스 안에서 동작하지 않으며 클래스 없이 리액트를 사용할 수 있게 해줍니다.

React Hook에 대해서는 다음번에 정리하여 공부해보겠습니다.

(너무 길어져서 나중에 읽기 힘들어질거같습니다,,,)

profile
안녕하세요. 매일 코딩하는 프론트엔드 개발자 입니다.

0개의 댓글