아래 내용은 우아한테크: [10분 테코톡] 마루의 리액트 컴포넌트 LIFECYCLE 영상을 참고한 글입니다. 유익한 내용 발표해주신 마루 님께 감사를 표하며, 영상을 통해 학습한 내용을 아래에 정리해 보았습니다.
브라우저가 렌더링에 필요한 DOM 트리를 만드는 과정 (컴포넌트 호출)
React는 2단계를 거쳐 화면에 UI를 렌더링 한다.
※ 참조: velog - [React] React의 렌더링 프로세스
컴포넌트가 생성, 변경, 제거되는 사이클을 말하며 크게 3가지로 구분한다.
컴포넌트가 화면에 보이기 시작할 때, 컴포넌트가 처음 DOM에 추가될 때
리렌더링, 상태(state)나 props가 변경되면 실행된다.
컴포넌트가 화면에서 사라질 때, 컴포넌트가 DOM에서 제거될 때
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
이렇게 한 사이클이 돌면 마운트가 완료된다.
state를 업데이트해서 리렌더링을 트리거 하게 되면 Update 과정을 거치게 된다.
Update 과정에서는 마운트에서처럼 Render와 React updates DOM 과정을 거친 후 layoutEffect가 실행되기 전에 정리 함수가 먼저 실행된다.
LayoutEffect 실행 전에 LayoutEffect 정리함수가 실행이 되고, Effect 실행 전에 Effect 정리함수가 실행된다.
컴포넌트가 제거되는 시점을 언마운트라고 할 수 있다.
언마운트 시점에는 각각의 정리함수만 실행되고 컴포넌트가 제거되게 된다.
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 → Cleanup LayoutEffects → LayoutEffects → Cleanup Effects → Effects 순서대로 콘솔에 찍힌 것을 확인할 수 있다.
이 테스트를 통해 상단의 이미지와 동일하게 코드가 동작한다는 것을 알 수 있다.