[React] 함수 컴포넌트의 LifeCycle

SungWoo·2025년 1월 13일
1

React

목록 보기
15/16

아래 내용은 우아한테크:  [10분 테코톡] 마루의 리액트 컴포넌트 LIFECYCLE 영상을 참고한 글입니다. 유익한 내용 발표해주신 마루 님께 감사를 표하며, 영상을 통해 학습한 내용을 아래에 정리해 보았습니다.

📌 리액트의 렌더링

브라우저가 렌더링에 필요한 DOM 트리를 만드는 과정 (컴포넌트 호출)

React는 2단계를 거쳐 화면에 UI를 렌더링 한다.

  1. Render Phase: 컴포넌트를 계산하고 업데이트(변경) 사항을 파악하는 단계
  2. Commit Phase: 변경사항을 실제 DOM에 반영하는 단계

※ 참조: velog - [React] React의 렌더링 프로세스

📌 컴포넌트의 생명주기란?

컴포넌트가 생성, 변경, 제거되는 사이클을 말하며 크게 3가지로 구분한다.

1. Mount(마운트)

컴포넌트가 화면에 보이기 시작할 때, 컴포넌트가 처음 DOM에 추가될 때

2. Update(업데이트)

리렌더링, 상태(state)나 props가 변경되면 실행된다.

3. UnMount(언마운트)

컴포넌트가 화면에서 사라질 때, 컴포넌트가 DOM에서 제거될 때

📌 함수 컴포넌트의 생명주기

1️⃣ 함수 컴포넌트의 생명주기 (Mount)

1) Run lazy initailizers (게으른 초기화)

  • lazy initializers로 초기화 된 state는 컴포넌트가 마운트 될 때만 실행된다.

useState의 초기값을 함수의 반환값으로 설정해야되는 경우

const 무거운_연산_함수 = counter => {
	console.log('0. 무거운 연산 실행');
	return Array.from({ length: 10 }, (_, i) => i + 1).reduce((acc, cur) => acc + cur, counter);
};

const TestApp = () => {
	const [counter, setCounter] = useState(무거운_연산_함수(0));
	
	console.log('1. Render / counter : 56')
	
	...
};

export default TestApp;
  • 🔎 출력 이미지

컴포넌트가 리렌더링 될때마다 함수가 호출된다.

const 무거운_연산_함수 = counter => {
	console.log('0. 무거운 연산 실행');
	return Array.from({ length: 10 }, (_, i) => i + 1).reduce((acc, cur) => acc + cur, counter);
};

const TestApp = () => {
	const [counter, setCounter] = useState(() => 무거운_연산_함수(0));
	
	console.log('1. Render / counter : 56')
	
	...
};

export default TestApp;
  • 🔎 출력 이미지

Lazy initializers를 사용하여 callback 함수로 넘기면 컴포넌트가 마운트될 때만 실행되고 리렌더링 될 때는 함수가 호출되지 않는 것을 확인할 수 있다.

JavaScript는 함수의 인자를 평가한 후에 그 결과를 함수에 전달하기 때문!

※ 참조: https://velog.io/@samkong/Lazy-initialization

2) Render

  • 함수 컴포넌트 내부 코드 실행
  • 가상 DOM에 발생할 변경 사항 기록
  • 렌더링 과정 중 렌더 단계에 해당

3) React updates DOM

  • Render에서 기록된 변경사항들을 가상 DOM에 적용
  • 렌더링 과정 중 커밋 단계에 해당

4) Run LayoutEffects

  • useLayoutEffect 훅에 전달된 콜백 함수를 실행하는 시점
  • 커밋 단계에서 실행
  • React가 가상 DOM의 변경 사항을 실제 DOM에 반영한 직후, 브라우저가 화면을 그리기 전에 실행됩니다.

5) Browser paints screen

  • 가상 DOM에 발생한 변경 사항들을 브라우저 DOM에 적용하는 시점 (브라우저 렌더링)
  • 페인팅이 끝나면 사용자는 화면에 컴포넌트가 그려진 것을 볼 수 있음

6) Run Effects

  • useEffect에 전달된 콜백함수가 호출되는 시점
  • 보통 이때 서버에 API 요청을 통해 데이터를 불러옴

이렇게 한 사이클이 돌면 마운트가 완료된다.


2️⃣ 함수 컴포넌트의 생명주기 (Update)

state를 업데이트해서 리렌더링을 트리거 하게 되면 Update 과정을 거치게 된다.

Update 과정에서는 마운트에서처럼 Render와 React updates DOM 과정을 거친 후 layoutEffect가 실행되기 전에 정리 함수가 먼저 실행된다.

LayoutEffect 실행 전에 LayoutEffect 정리함수가 실행이 되고, Effect 실행 전에 Effect 정리함수가 실행된다.

1) Cleanup LayoutEffects

  • useLayoutEffect에 전달된 정리함수가 호출되는 시점
  • 정리 함수가 실행된 후 useLayoutEffect 실행

2) Cleanup Effects

  • useEffect에 전달된 정리함수가 호출되는 시점
  • 정리 함수가 실행된 후 useEffect 실행

3️⃣ 함수 컴포넌트의 생명주기 (UnMount)

컴포넌트가 제거되는 시점을 언마운트라고 할 수 있다.

언마운트 시점에는 각각의 정리함수만 실행되고 컴포넌트가 제거되게 된다.

1) Cleanup LayoutEffects

  • 언마운트 될 때마다 정리 함수 실행

2) Cleanup Effects

  • 언마운트 될 때마다 정리 함수 실행

✅ 콘솔 테스트

import { useState, useLayoutEffect, useEffect } from 'react';

const 무거운_연산_함수 = counter => {
    console.log('0. 무거운 연산 실행');
    return Array.from({ length: 10 }, (_, i) => i + 1).reduce((acc, cur) => acc + cur, counter);
};

const TestApp = () => {
    const [counter, setCounter] = useState(() => 무거운_연산_함수(0));

    const handleClick = () => {
		    console.log("클릭");
        setCounter(counter => counter + 1);
    };
    
    console.log("1. Render / counter : ", counter);

    useLayoutEffect(() => {
        console.log('2-2. Run LayoutEffects / counter : ', counter);
        return () => console.log('2-1. Cleanup LayoutEffects / counter : ', counter);
    });

    useEffect(() => {
        console.log('3-2. Run Effects / counter : ', counter);
        return () => console.log('3-1. Cleanup Effects / counter : ', counter);
    });

    return (
        <div>
            <button onClick={handleClick}>클릭</button>
        </div>
    );
};

export default TestApp;
  • 🔎 출력 이미지
초기 렌더링에서는 Render → LayoutEffect → Effect 순서대로 콘솔에 찍힌 것을 확인할 수 있다.

이후 클릭을 통해 리렌더링을 발생시켜서 컴포넌트를 재호출 해보면 Render → Cleanup LayoutEffects → LayoutEffects → Cleanup Effects → Effects 순서대로 콘솔에 찍힌 것을 확인할 수 있다.

이 테스트를 통해 상단의 이미지와 동일하게 코드가 동작한다는 것을 알 수 있다.

profile
어제보다 더 나은

0개의 댓글