배경
RN을 배우기 시작하면서 React와 RN의 렌더링 간에 어떤 차이점이 있는지 궁금했고, 평소 React의 렌더링 방식에 무지했던 것 같아 궁금했던 점들을 하나씩 정리해보려고 합니다.
setState를 호출할 때마다 즉시 리렌더링이 발생하는가?
import { useState } from 'react';
export default function Counter() {
const [number, setNumber] = useState(0);
return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(n => n + 1);
setNumber(n => n + 1);
setNumber(n => n + 1);
}}>+3</button>
</>
)
}
아닙니다. React는 state 업데이트를 하기 전에 이벤트 핸들러의 모든 코드가 실행될 때까지 기다립니다. 이 때문에 리렌더링은 모든 setNumber() 호출이 완료된 이후에만 일어납니다.
이를 Batching(배칭)이라고 합니다. Batching이란 여러 개의 상태 업데이트를 하나의 "배치"로 묶어서 처리함으로써, 불필요한 리렌더링을 방지하고 성능을 최적화하는 기법입니다. React에서는 상태가 바뀔 때마다 컴포넌트를 다시 렌더링하는데, 여러 번 연속으로 상태를 바꿀 경우 이를 하나의 렌더로 합치는 것이 배칭입니다.
업데이트 큐
import { useState } from 'react';
export default function Counter() {
const [number, setNumber] = useState(0);
return (
<>
<h1>{number}</h1>
<button onClick={() => {
setNumber(n => n + 1);
setNumber(n => n + 1);
setNumber(n => n + 1);
}}>+3</button>
</>
)
}
React 내부에서는 함수 컴포넌트가 렌더될 때 훅들이 순서대로 Linked List 형태로 구성되는데, 각 훅 객체마다 queue 프로퍼티를 가지고 있습니다. 여기서 queue는 state 업데이트로 들어온 액션들을 모아두는 Circular Linked List입니다. 각 훅마다 서로 다른 업데이트 큐를 가지고 있기 때문에 업데이트는 절대 같은 큐에 섞이지 않습니다.
const hook: Hook = {
memoizedState: null,
baseState: null,
queue: null,
baseUpdate: null,
next: null,
};
setState 함수에 전달하는 n => n + 1을 업데이터 함수(Updater Function)라고 부릅니다.
- setNumber에 업데이트 함수가 전달되면, 업데이트 함수는 useState의 업데이트 큐에 쌓입니다.
- 이벤트 핸들러 함수가 종료되고 리렌더링이 시작된 후 useState를 호출하면, React는 해당 useState의 업데이트 큐를 순회합니다.
- 큐에 쌓인 순서대로 업데이트 함수를 꺼내서 실행하고 최종적으로 반환된 3이라는 결과를 useState에서 반환합니다.
Virtual DOM과 Fiber는 어떤 차이가 있을까?
Virtual DOM은 실제 브라우저 DOM을 추상화한 자바스크립트 객체 트리입니다. React는 컴포넌트 렌더링 결과를 이 가상 DOM으로 먼저 표현하고, 이전 가상 DOM과 비교하여 최소한의 변경사항만 실제 DOM에 반영합니다. 이 과정을 통해 불필요한 레이아웃 계산과 스타일 재계산을 줄여 성능을 최적화합니다. 매 렌더마다 새로 생성되며, 이전 가상 DOM과 비교 후 폐기되는 라이프사이클을 가졌습니다.
Fiber 트리는 React 내부 자료구조로, Virtual DOM의 업데이트 작업을 더 세밀하게 분할하고 스케줄링하기 위해 설계되었습니다. 각 Fiber 노드는 컴포넌트 1개와 대응하며, 이전 렌더의 props/state, 업데이트 큐, 자식/형제/부모 포인터 등을 가지고 있습니다. 랜더마다 재사용됩니다.
즉, Virtual DOM은 "무엇이 바뀌었는지"를 계산하는 자료구조이고, Fiber 트리는 그 계산 작업을 "언제, 어떻게" 브라우저에 반영할지 스케줄링하는 엔진이라고 볼 수 있습니다.
'IT > Front-End' 카테고리의 다른 글
버전 꼬임 이제 그만: Cursor AI로 ‘update:minor’ 한 줄에 끝낸 릴리즈 혁명 (1) | 2025.05.13 |
---|---|
[FE] 브라우저 동작방식 (0) | 2025.05.05 |
[Next.js] 의존성 그래프를 활용한 프로젝트 시각화 활용 (1) | 2025.04.21 |
[React] useWebNotification (0) | 2025.04.19 |
[React] useOnClickOutside (0) | 2025.03.25 |