Fiber는 React 16부터 쓰는 내부 자료구조이자 렌더링 엔진이다. 엘리먼트마다 Fiber 노드를 만들어 렌더 작업을 작은 단위로 쪼개고, 우선순위를 매기고, 중간에 멈췄다 다시 이어 갈 수 있게 한다.
- 왜 생겼나: React 15까지는 렌더를 한 번 시작하면 트리 끝까지 동기로 돌았다. 큰 목록을 그리는 동안 메인 스레드가 막혀 입력과 스크롤이 끊겼다(이벤트 루프)
- 작업 단위: 큰 렌더 하나를 Fiber 단위의 작은 일로 나눈다. 그 사이에 더 급한 일(사용자 입력)을 먼저 처리할 수 있다(동시성 렌더링)
- 연결 리스트(Linked List) 구조: 각 Fiber는
child(첫 자식),sibling(다음 형제),return(부모)로 이어져 있어서, 재귀 호출 없이 어디서든 멈추고 이어 갈 수 있다(연결 리스트, 트리 순회) - 주요 필드:
type,key,stateNode(실제 DOM(Document Object Model) 등),pendingProps·memoizedProps,memoizedState(훅 상태),alternate
두 단계와 더블 버퍼링(Double Buffering)
- Render 단계(Render Phase): 새 트리를 계산하고 바뀐 점을 모은다. DOM을 건드리지 않으며 중단될 수 있다. 그래서 렌더 함수는 순수해야 한다(React의 규칙과 렌더 순수성)
- Commit 단계(Commit Phase): 모은 변경을 실제 DOM에 한 번에 반영한다. 중단할 수 없다
React는 트리를 두 벌 둔다. 화면에 반영된 current와, 렌더 단계에서 짓는 workInProgress다. 커밋할 때 포인터만 바꿔 끼운다. 그래픽스의 더블 버퍼링(보이는 앞 버퍼와 그리는 중인 뒤 버퍼를 나눠 다 그린 뒤 교체)과 같은 구조라서, 렌더가 도중에 버려져도 사용자는 반쯤 그려진 화면을 보지 않는다. 두 트리의 대응 노드는 alternate로 이어져 재사용된다.
flowchart TD U[업데이트] --> R["Render 단계: workInProgress 트리를 짓고 바뀐 점을 모음"] R -- 중단·버림 --> K["current 그대로 (반쯤 그린 화면은 안 보임)"] R --> C["Commit 단계: 모은 변경을 DOM에 한 번에 반영 (중단 불가)"] C --> S["포인터 교체: workInProgress가 새 current"] S -. 다음 업데이트 .-> U
Suspense, useTransition, 스트리밍 SSR, 선택적 하이드레이션이 모두 이 위에서 동작한다. 엘리먼트와의 관계는 React 엘리먼트와 JSX.