탐색으로 돌아가기
React21 / 24 단계

Fiber

작업 단위 · 우선순위

Fiber는 React 16+의 재조정 엔진. 렌더링을 작은 단위로 나눠 중단·재개하고, 급한 업데이트를 먼저 처리한다.

Fiber는 React 16부터 도입된 재조정 엔진의 핵심 자료구조이자 실행 모델로, 각 컴포넌트 인스턴스에 대응하는 '작업 단위(unit of work)'를 나타내는 JavaScript 객체다. 기존 스택 기반 재귀 재조정은 한 번 시작하면 끝까지 동기적으로 실행되어 중단할 수 없었지만, Fiber는 트리를 연결 리스트(child/sibling/return 포인터)로 재구성해 작업을 잘게 쪼개고 중단·재개·우선순위 재조정을 가능하게 했다. React는 화면에 보이는 current 트리와 백그라운드에서 만드는 work-in-progress 트리를 동시에 유지하는 더블 버퍼링(double buffering)을 사용하며, 커밋 시점에 두 트리의 포인터를 스왑한다. 각 업데이트에는 우선순위를 나타내는 lane(31개 lane의 비트마스크 — React의 TotalLanes = 31; 32비트 정수에 담기지만 실제로는 31비트만 사용)이 부여되고, 스케줄러(Scheduler)가 브라우저의 유휴 시간을 활용해 타임 슬라이싱으로 작업을 배분하며 급한 작업(예: 입력)이 오면 낮은 우선순위 렌더를 중단한다. 재조정은 각 Fiber에서 하향(beginWork)과 상향(completeWork) 두 국면으로 진행되며, 그 결과 부작용이 있는 노드들이 effect list에 모여 커밋 단계로 전달된다.

내부 구성

Fiber 노드 (Fiber Node)
컴포넌트 인스턴스 하나에 대응하는 작업 단위 객체. 타입·상태·포인터·부작용 플래그를 보관한다
child / sibling / return 포인터
트리를 단일 연결 리스트처럼 순회 가능하게 만드는 링크. return은 부모, child는 첫 자식, sibling은 다음 형제
current 트리
현재 화면에 커밋되어 사용자에게 보이는 Fiber 트리
work-in-progress 트리
백그라운드에서 새로 구축 중인 Fiber 트리. 완성되면 current와 스왑된다
alternate 포인터
current Fiber와 work-in-progress Fiber를 서로 연결해 더블 버퍼링에서 재사용을 가능케 하는 링크
Lanes (우선순위 레인)
업데이트 우선순위를 표현하는 31-lane 비트마스크(32비트 정수, 31비트 사용). SyncLane, InputContinuousLane, DefaultLane, TransitionLane 등
Scheduler (스케줄러)
별도 패키지. 우선순위별 콜백을 관리하고 브라우저에 제어권을 양보(yield)하며 타임 슬라이싱을 구현
타임 슬라이싱 (Time Slicing)
렌더 작업을 5ms 내외 청크로 쪼개 프레임마다 양보, 메인 스레드 블로킹과 프레임 드랍을 방지
beginWork
하향 국면 함수. 해당 Fiber의 컴포넌트를 렌더하고 자식 Fiber를 생성/재조정한다
completeWork
상향 국면 함수. 호스트 인스턴스(DOM 노드)를 생성/준비하고 부작용 플래그를 부모로 버블링한다
effect list / flags
부작용(삽입·삭제·갱신·effect)이 있는 Fiber를 표시. 커밋 단계에서 순회할 대상 집합을 형성
stateNode
Fiber가 관리하는 실제 인스턴스에 대한 참조. 호스트 컴포넌트면 DOM 노드, 클래스면 인스턴스

핵심 포인트

  • Fiber 노드 = 하나의 작업 단위. type, key, stateNode, 그리고 child/sibling/return 포인터와 pendingProps/memoizedState/flags 등을 담는다
  • 스택 재귀를 연결 리스트 순회로 바꿔 렌더 작업을 중단(pause)·재개(resume)·폐기(abort)할 수 있게 만든 것이 Fiber의 본질
  • 더블 버퍼링: current 트리(화면 반영본) vs work-in-progress 트리(작업본), alternate 포인터로 상호 연결, 커밋 때 스왑
  • lanes: 우선순위 레벨을 나타내는 31개 lane의 비트마스크(React TotalLanes = 31, 32비트 정수에 담되 31비트만 사용). 여러 업데이트의 우선순위를 효율적으로 병합/비교
  • Scheduler가 requestIdleCallback 유사 메커니즘(실제로는 MessageChannel)으로 타임 슬라이싱, 프레임을 양보(yield)
  • beginWork(하향): 컴포넌트 render 호출 후 자식 Fiber 생성/재조정. completeWork(상향): 호스트 인스턴스 준비 및 effect 수집
  • effect list(현대엔 flags/subtreeFlags 기반)로 부작용이 있는 Fiber만 추려 커밋 단계에 전달

심화

Fiber를 이해하는 열쇠는 '왜 스택을 버렸는가'다. 기존 재귀 재조정은 콜 스택에 작업 진행 상태가 갇혀 있어 중간에 멈추면 그 상태를 저장할 방법이 없었다. Fiber는 진행 상태를 힙(heap)의 객체(Fiber 노드)로 외부화함으로써, 작업을 멈췄다가 나중에 정확히 그 지점부터 재개할 수 있는 '재개 가능한 스택 프레임'을 소프트웨어로 구현한 것이다. 이것이 Concurrent React(useTransition, useDeferredValue, Suspense 스트리밍)의 토대가 된다. 면접 포인트로 자주 나오는 것: (1) 렌더 단계는 중단 가능하지만 커밋 단계는 반드시 동기·비중단이다 — 그래서 중단 가능한 렌더 중에는 부작용을 절대 실행하면 안 된다. (2) Concurrent 모드에서 컴포넌트가 두 번 렌더될 수 있는 이유 — React가 낮은 우선순위 렌더를 폐기하고 다시 시도할 수 있기 때문이며, StrictMode의 이중 호출도 이런 순수성 강제의 연장선이다. (3) lanes가 단순 숫자 우선순위가 아니라 비트마스크인 이유 — 여러 업데이트가 어느 lane들에 걸쳐 있는지 한 번의 비트 연산으로 병합·검사·배제할 수 있어 우선순위 계산이 O(1)에 가깝기 때문이다.

쉽게 말하면 큰 공사를 작은 작업 티켓(Fiber)으로 나눠, 급한 티켓부터 처리하고 언제든 멈췄다 재개하는 것.

면접 예상 질문

#Fiber#Reconciliation#Concurrent#우선순위#effect list