리액트의 내부 동작을 깊이 이해하기 위해 직접 리액트를 구현해보는 튜토리얼을 진행했다.
지금보면 코드가 눈에 다 들어와서 별로 복잡해보이진 않지만, 처음에는 코드를 이해하는게 힘들었다.
링크드 리스트처럼 노드마다 부모, 자식, 형제로 얼키설키 엮여 있는 구조와
Fiber 노드 객체의 속성과 뎁스가 너무 많아 코드를 파악하기 어려웠다.
이런 문제를 해결하기 위해 각 노드 객체의 관계를 그림으로 직접 그려보며 구조를 하나씩 이해해나갔다.
튜토리얼을 통해 파악한 주요 개념들을 정리해보았다.
1. Fiber란?
1) 정의
Fiber는 각 DOM 노드(element)마다 생성되는 객체로, Fiber Tree를 구성하는 작업 단위이다.
Fiber Tree는 렌더링 프로세스를 관리하기 위한 구조인데,
이를 기반으로 react는 DOM Tree를 업데이트를 효율적으로 관리하고 최적화한다.
Fiber로 작업 단위를 나누는 이유는?
아래에 설명할 동시성 렌더링(Concurrent Rendering)을 하기 위해서다.
Fiber Tree 생성 작업을 한 번에 처리하지 않고, 우선순위가 높은 작업이 있다면 Fiber 생성을 중단 했다가
다시 idle 상태에서 이어서 처리하기 위해서이다.
2) Fiber의 구조
const fiber = {
type: "div",
props: {
id: "root",
className: "container",
children: [],
},
parent: null,
sibling: null,
child: null,
dom: null,
alternate: null,
effectTag: ""
};
3) Fiber Tree 예제
function App() {
return (
<div>
<h1>
<p>p</p>
<a>a</a>
</h1>
<h2></h2>
</div>
);
}
const container = document.getElementById("root");
const element = <App />;
Didact.render(element, container);
위 코드의 Fiber Tree는 아래와 같이 구성된다.
h1 노드의 fiber를 출력해보면 실제 이런식으로 구성되어있다.
h1 노드의 Fiber는 부모, 자식, 형제 관계가 객체 형태로 모두 연결되있다.
2. 동시성 렌더링 (Concurrent Rendering)
1) 정의
동시성 렌더링은 Fiber 조작(생성, 삭제, 수정)을 한 번에 처리하지 않고, idle 상태에서 작업을 나누어 처리하며
우선순위가 높은 작업이 즉시 처리되도록 설계된 React 렌더링 모델이다.
이를 통해 더 중요한 작업(ex: 사용자 인터랙션)을 우선 처리하여 사용자 경험을 개선할 수 있다.
(React 18 버전부터 도입된 기능)
2) 특징
- 작업 단위 쪼개기: Fiber Tree를 만드는 과정을 나누어 처리한다. 그 나눈 작업 단위를 Fiber 라고 한다.
- Idle 상태 활용: Fiber 조작 과정은 idle 상태(유휴 상태)일 때 진행된다.
- 작업 우선순위 설정: 더 중요한 작업(예: 사용자 입력)은 우선 처리한다. (이땐 idle 상태가 아니게됨)
3) 필요성
동시성 렌더링이 없으면?
fber 생성 과정이 중단되지 않고 한번에 진행된다.
그래서 도중 사용자 인터렉션이 발생한면 사용자 인터렉션 작업은 뒤로 밀리게된다.
→ 결과적으로 사용자 경험이 저하된다.
동시성 렌더링이 있으면?
fber 생성 작업이 나뉘어 idle 상태에서 처리되므로, 사용자 입력과 같은 우선순위가 높은 작업이 즉시 처리된다.
→ 결과적으로 사용자 경험이 개선된다.
4) 구현
튜토리얼에서는 window.requestIdleCallback을 사용해 idle 상태를 감지하고, 이 상태에서 Fiber 생성 작업을 진행했다.
그러나 이는 학습을 위한 구현이고, 실제 React는 자체적으로 스케줄링 알고리즘을 구현했다. (React 코드 참고)
React는 Scheduler 패키지를 사용하여 우선순위와 작업 시간을 관리한다.
(requestIdleCallback는 사파리에서 지원하지 않는다고 한다.)
3. Commit 단계
커밋 단계에서는 생성된 Fiber Tree를 기반으로 DOM Tree에 최종 렌더링 작업 실행한다.
Fiber 속성인 effectTag를 통해 DOM 노드의 생성, 수정, 삭제를 결정한다. 이 작업은 한 번에 처리된다.
4. 재조정 (Reconciliation)
1) 정의
재조정은 리렌더링시, 가상 DOM과 실제 DOM을 비교하여 변경된 부분만 업데이트하는 과정이다.
이를 통해 불필요한 DOM 업데이트를 줄이고 성능을 최적화할 수 있다.
2) 구현
- 이전 Fiber와 비교하여 변경된 부분만 새롭게 생성된 Fiber로 대체합니다.
- Fiber Tree를 새로 구성한 뒤
- 똑같이 Commit 단계에서 변경된 부분만 실제 DOM에 반영하게 된다.
<마치며>
리액트의 내부 구현 원리를 이렇게 딥하게 파악한건 처음이다.
여태까지 나는 누군가 잘 정리해논 포스팅 글을 보며 공부하곤 했는데
직접 이렇게 코드를 파보고 짜보면서 이해하니, 더 체감되는게 크게 느껴진다.
Deep Dive라는게 이런거구나 라는 생각도 든다.
참조사이트
'프론트엔드 > React' 카테고리의 다른 글
클로저를 활용해 useState Hook 직접 구현해보기 (0) | 2025.03.02 |
---|---|
Controlled vs Uncontrolled (input요소 value와 defaultValue 차이) (1) | 2025.02.16 |
useState 의 setState는 비동적으로 동작 (0) | 2024.05.06 |
useMemo, useCallback에 대해 (0) | 2023.12.10 |
[TIL] React router6 (0) | 2023.09.17 |