React Fiber란?
Fiber는 React 16부터 도입되어 18부터 본격적으로 사용된 재조정(Reconciliation) 알고리즘이다. React의 초기 버전은 재귀 호출을 사용하여 Stack 구조에서 가상 DOM 트리를 탐색하고 업데이트를 적용했지만, 이는 대규모 애플리케이션에서 성능 문제가 발생할 수 있었다. Fiber는 이러한 문제를 해결하고자 리액트의 내부 구조를 혁신적으로 개선한 기술이다.
React의 주요 패키지 구성요소
🛠 React (Core)
컴포넌트 작성, JSX 지원, Hook, 라이프사이클 메서드 등을 제공하는 패키지다. 다른 패키지에 의존성이 없으므로 다양한 플랫폼(브라우저-DOM, 모바일-Native)에 올려서 사용 가능하다.
🛠 Renderer
react-dom, react-native-renderer 등 호스트 렌더링 환경에 의존하여 렌더링을 담당하는 패키지다.
호스트와 React를 연결하고 즉, 웹에서는 DOM을 조작하는 역할을 한다.
reconciler와 legacy-events 패키지에 의존성이 있다.
🛠 Event(legacy-events)
https://legacy.reactjs.org/docs/events.html (legacy doc)
합성이벤트(SyntheticEvent)라는 이름의 내부적으로 개발된 이벤트 시스템이다.
기존 웹에서의 event를 wrapping하여 추가적인 기능을 수행할 수 있게 한다.
🛠 Scheduler
React는 Render Phase에서 Task를 비동기로 실행하는데, Scheduler는 이 Task를 실행하는 타이밍을 알고 있는 패키지다.
🛠 Reconciler
fiber architecture에서 VDOM 재조정을 담당한다.
React (Core)에서 정의된 컴포넌트를 호출하는 곳이다.
기존 재조정 알고리즘(Stack Reconciliator)의 한계
초기 리액트의 재조정 알고리즘은 주로 스택 기반 재귀 호출을 사용하여 컴포넌트 트리를 탐색하고 업데이트를 적용했다. 이는 몇 가지 한계를 가지고 있었다:
- 동기적 처리
- 모든 작업이 동기적으로 처리되기 때문에, 긴 렌더링 작업은 메인 스레드를 블록(block)시켜 사용자 인터페이스(UI)가 멈추는 현상이 발생할 수 있다.
- 우선순위 관리 부족
- 모든 업데이트 작업이 동일한 우선순위로 처리되어, 사용자 입력 같은 중요한 작업이 지연될 수 있다.
- 비효율적인 대규모 업데이트
- 대규모 컴포넌트 트리에서 변경 사항을 탐색하고 적용하는 데 시간이 오래 걸릴 수 있다.
Fiber의 도입
Fiber는 이러한 문제를 해결하기 위해 도입된 리액트의 새로운 재조정 알고리즘이다. Fiber는 기존의 스택 기반 접근 방식을 대신하여, 보다 유연하고 효율적인 방식으로 재조정을 수행한다.
Fiber의 주요 개념
- Fiber Node
- Fiber Node는 React 컴포넌트 트리의 각 요소를 나타내는 구조체다. 이전의 가상 DOM 노드와 유사하지만, 더 많은 정보를 포함하고 있다.
- 각 Fiber 노드는 컴포넌트의 상태, props, DOM 업데이트 정보 등을 포함한다.
- 단편화된 렌더링
- Fiber는 작업을 작은 단위로 분할하여 렌더링을 수행한다. 이를 통해 긴 렌더링 작업을 여러 프레임에 걸쳐 나눠서 수행할 수 있으며, 메인 스레드가 블록되지 않도록 한다.
- 우선순위 기반 업데이트
- Fiber는 각 업데이트에 우선순위를 부여하여, 중요한 작업(예: 사용자 입력 처리)이 우선적으로 처리될 수 있도록 한다.
Fiber의 주요 특징
- 비동기적 처리(Async Rendering)
- Fiber는 작업을 작은 단위로 분할하여, 긴 렌더링 작업을 여러 프레임에 걸쳐 나누어 수행할 수 있다. 이를 통해 메인 스레드가 블록되지 않고, 사용자 인터페이스가 더 부드럽게 동작한다.
- 우선순위 기반 스케줄링
- 각 작업에 우선순위를 부여하여 중요한 작업이 먼저 처리될 수 있도록 한다. 예를 들어, 사용자 입력 이벤트는 높은 우선순위를 가지며, 즉시 처리된다.
- 작업의 중단과 재개
- Fiber는 렌더링 작업을 중단하고 나중에 재개할 수 있다. 이를 통해 중요한 작업이 먼저 처리되고, 나머지 작업은 이후에 처리된다.
Fiber의 구조와 내부 동작
Fiber는 각 컴포넌트 트리의 노드를 관리하기 위한 새로운 데이터 구조를 도입한다. 이 데이터 구조는 각 컴포넌트의 렌더링 상태와 관련된 다양한 정보를 포함한다. 다음은 Fiber 노드의 주요 속성과 예시다.
🛠 Fiber 노드의 주요 속성
- type: 노드의 타입을 나타낸다. 예를 들어, 함수형 컴포넌트, 클래스 컴포넌트, 호스트 컴포넌트(HTML 태그) 등.
- key: React가 각 노드를 고유하게 식별하기 위한 키.
- child: 자식 노드를 가리키는 참조.
- sibling: 형제 노드를 가리키는 참조.
- return: 부모 노드를 가리키는 참조.
- stateNode: 해당 노드와 관련된 컴포넌트 인스턴스 또는 DOM 노드.
- pendingProps: 렌더링 대기 중인 새로운 props.
- memoizedProps: 이전 렌더링에서 사용된 props.
- updateQueue: 해당 노드에 대한 상태 업데이트 큐.
const fiberNode = { tag: 'div', key: null, elementType: 'div', type: 'div', stateNode: DOMNode, return: parentFiberNode, child: childFiberNode, sibling: siblingFiberNode, pendingProps: { className: 'container' }, memoizedProps: { className: 'container' }, memoizedState: null, updateQueue: updateQueueInstance, flags: 0 };
Fiber Node는 Virtual DOM 개념과는 다르다
Fiber Node는 React의 새로운 재조정 알고리즘을 지원하기 위해 설계된 자료구조다. 이는 보다 많은 정보를 포함하여 렌더링과 상태 관리를 효율적으로 수행할 수 있도록 한다. Fiber 노드는 다음과 같은 구조를 가진다. 반면 Virtual DOM 객체는 리액트 컴포넌트가 JSX로 작성된 UI를 설명하기 위해 사용된다.
- 구조적 차이
- 버추얼 DOM 객체는 단순히 UI를 설명하기 위한 구조로, 주로 타입, props, key 등을 포함한다.
- Fiber 노드는 더 많은 상태와 업데이트 정보를 포함하여, 렌더링 및 재조정 과정을 효율적으로 관리할 수 있게 설계되었다. Fiber 노드는 부모, 자식, 형제 노드에 대한 참조를 가지고 있으며, 상태 및 업데이트 큐를 관리한다.
- 목적
- 버추얼 DOM 객체는 UI의 현재 상태를 설명하는 역할을 한다. 이는 컴포넌트가 렌더링될 때마다 생성된다.
- Fiber 노드는 렌더링과 재조정(Reconciliation) 과정을 관리하기 위해 사용된다. 이는 각 컴포넌트의 상태, props, 업데이트 정보를 유지하고, 렌더링 작업을 보다 세밀하게 제어할 수 있게 한다.
- 업데이트 관리
- 버추얼 DOM 객체는 상태나 props가 변경될 때마다 새로 생성되어 기존의 객체와 비교된다.
- Fiber 노드는 지속적으로 유지되며, 업데이트 정보를 통해 상태 변화와 재조정을 관리한다. Fiber 노드는 렌더링 작업을 중단하고 재개할 수 있어 비동기적 렌더링을 지원한다.
- 연결 구조
- 버추얼 DOM 객체는 트리 구조로, 각 노드는 자식 노드 배열을 포함한다.
- Fiber 노드는 트리 구조와 링크드 리스트(linked list) 구조를 혼합한 형태로, 부모, 자식, 형제 노드 간의 참조를 통해 트리를 탐색할 수 있다.
Fiber의 장점
- 향상된 성능
- 비동기 렌더링과 우선순위 기반 업데이트를 통해 애플리케이션의 성능이 크게 향상된다.
- 사용자 인터페이스의 응답성이 높아지며, 복잡한 애플리케이션에서도 부드러운 렌더링을 제공한다.
- 유연한 업데이트 관리
- 작업을 작은 단위로 분할하여 필요한 경우 언제든지 중단하고 재개할 수 있다. 이를 통해 중요한 작업이 지연되지 않도록
보장한다.
- 업데이트 우선순위를 조정하여 중요한 작업이 우선적으로 처리될 수 있다.
3. 개선된 사용자 경험
- 긴 렌더링 작업이 메인 스레드를 블록하지 않기 때문에, 사용자 입력에 대한 반응이 더 빠르고 부드럽다.
- 애니메이션과 같은 인터페이스 요소들이 더 매끄럽게 동작한다.