본문 바로가기
이론/Frontend

리액트 컴포넌트 생명주기 (React Component Life Cycle)

by 유세지 2022. 5. 1.

리액트를 공부하며

이번에 리액트를 본격적으로 사용하게 되었습니다. 그동안 리액트 자체를 사용해보긴 했지만 어떻게 사용해야하는지에 대한 고민이나 공부없이 말 그대로 쓰기만 했었습니다. 그래서, 이번 기회에 기초부터 차근차근 공부해보려 합니다.

 

오늘은 리액트 컴포넌트의 생명주기에 대해 알아보겠습니다. 글을 쓰는 현재 리액트 18버젼이 나왔기 때문에, 17버젼에서 이미 deprecate된 일부 단계들은 다루지 않습니다.

 

 

1. componentDidMount

컴포넌트가 마운트(mount)되며 일어나는 단계입니다. 위키백과에서는 마운트(mount)에 대해 "컴퓨터 과학에서 저장 장치에 접근할 수 있는 경로를 디렉터리 구조에 편입시키는 작업을 말한다." 라고 설명합니다. 이처럼 컴포넌트가 처음 실행되면 컴포넌트의 내용을 DOM 구조에 편입시키는 과정인 렌더링이 먼저 진행되고, 이후에 componentDidMount에 선언된 내용이 실행됩니다.

 

import React, { Component } from 'react'

// Class Component
export default class MyComponent extends Component {
  ...

  componentDidMount() {
    // 실행될 내용
  }

  ...
}

// Function Component
const MyComponent = () => {
  ...
  useEffect(() => {
    // 실행될 내용
  }, [])

  ...
}

export default MyCompoent;

 

클래스 컴포넌트에서는 componentDidMount() 메서드 내부의 내용에 실행될 내용을 입력하여 마운트가 완료된 시점에 실행할 동작들을 선언해 줄 수 있고, 함수 컴포넌트에서는 useEffect 훅 내부에 실행할 동작들을 선언하고, 두 번째 인자에 들어가는 배열을 비워줌으로써 componentDidMount() 처럼 동작하도록 할 수 있습니다.

 

 

2. componentDidUpdate

다음은 componentDidUpdate 입니다. 컴포넌트가 업데이트 되어야 할지를 결정하는 shouldComponentUpdate 단계에서 컴포넌트를 업데이트 하기로 결정하면 리렌더링이 발생하고, 업데이트가 완료되면 componentDidUpdate 단계에 오게 됩니다. 

 

import React, { Component } from 'react'

// Class Component
export default class MyComponent extends Component {
  ...

  componentDidUpdate() {
    // 실행될 내용
  }

  ...
}

// Function Component
const MyComponent = () => {
  const prevCountRef = useRef();
  ...
  useEffect(() => {
    if (prevCountRef.current) {
      // 실행될 내용
    } else {
      prevCountRef.current = true;
    }
  });

  ...
}

export default MyCompoent;

 

클래스 컴포넌트에서는 마찬가지로 componentDidUpdate() 메서드 내부에 실행할 내용을 적어주면 됩니다. 다만 함수 컴포넌트에서는 조금 다른데, useEffect 훅 내부에 해당 로직이 포함되어 있기 때문에 useRef 훅을 사용하여 분리해줘야합니다. 우리는 이것과 비슷한 로직을 전에도 구현해보았는데요, 바로 클로저를 이용한 대표적인 최적화 기법인 쓰로틀에서도 유사한 방식으로 구현했었습니다. 리액트 공식문서에서는 이러한 작업이 드문 사용 사례라고 하지만, 알아두면 좋을 것 같네요!

 

리액트 공식문서 'Hook 자주 묻는 질문' 페이지 중

 

 

3. componentWillUnmount

마지막은 컴포넌트가 Unmount 되려고 하는 시점입니다. 더는 사용되지 않는 컴포넌트가 제거될때, 그 직전 상태에서 해줘야 할 작업들을 선언해주는 단계입니다.

 

한 가지 주의해야 할 점은, componentWillUnmount는 컴포넌트가 Unmount 되는 시점이기 때문에, 페이지 자체를 벗어나려고 시도하거나 브라우저를 종료하는 동작을 했을때 일어나는 단계인 window의 beforeunload와는 차이가 있습니다. 따라서 사용자가 페이지를 벗어나려고 할 때 경고창을 띄우는 등 종료 시점에 발생해야 할 동작들을 componentWIllUnmount 단계에 선언하게 되면 해당 동작이 실행되기도 전에 페이지를 벗어나게 되어 의도한 동작을 수행할 수 없을 것입니다.

 

import React, { Component } from 'react'

// Class Component
export default class MyComponent extends Component {
  ...

  componentWillUnmount() {
    // 실행될 내용
  }

  ...
}

// Function Component
const MyComponent = () => {
  ...
  useEffect(() => {
    ...
    return () => {
      // 실행될 내용
    }
  });

  ...
}

export default MyCompoent;

 

useEffect의 return 부분에 함수를 넣어주게 되면 컴포넌트가 Unmount 될때 해당 내용을 실행하게 됩니다. 이렇게보니 useEffect가 하는 일이 참 많네요.

 

추가로, 컴포넌트가 Unmount 된 이후의 시점에는 컴포넌트 내부의 코드가 동작할 수 없으니 componentDidUnmount 라는 단계는 없습니다😊

 

마무리

오늘 함수 컴포넌트로의 변환에서 많이 사용했던 use... 함수들은 클래스 컴포넌트의 기능들을 함수 컴포넌트에서 사용할 수 있게 해주는 기술들로, 훅(Hook)이라고 부릅니다. 이에 대해서는 따로 포스트를 작성할 예정이라서 깊게 설명하지 않았습니다. 잘 정리해서 빠른 시일내로 올려보도록 하겠습니다.

 

읽어주셔서 감사합니다.

 

 

참고 문서

업데이트에만 effect를 실행할 수 있습니까? - React docs

인스턴스 변수와 같은 것이 있습니까? - React docs

Hooks API Reference - React docs

 

댓글