FEInterview Prep

react · high priority

React Fiber — 중단·재개 가능한 재조정 엔진

Stack Reconciler 가 풀지 못한 응답성 문제와 Fiber 의 해법

advanced 난이도6시간토스카카오네이버당근배민라인
시작 전
이해도
매우 낮음

학습 개요

탄생 배경

쉬운 설명

복잡한 개념을 실생활 비유로 설명합니다.

레스토랑의 새 주방장과 주문 보드

예전 주방(Stack Reconciler)은 한 번에 한 주문만 받아 끝까지 만들었습니다. 코스 주문이 들어오면 손님이 마실 물도 그동안 못 내갔죠. 새 주방장(Fiber)은 모든 주문을 *주문 보드*(Fiber 트리) 에 적어두고, 짧은 단위로 이 주문 → 저 주문을 옮겨다닙니다. VIP 가 들어오면(높은 우선순위) 만들던 코스를 잠시 미뤄 그쪽 음료부터 갑니다. 손님이 갑자기 메뉴를 바꾸면 만들던 접시를 버리고(work-in-progress 폐기) 새 주문을 시작합니다.

핵심 개념

Stack vs Fiber Reconciler

Stack Reconciler (~React 15)
  • 재귀 호출 스택이 곧 작업 진행 상태
  • 중단 불가 → 큰 트리 업데이트가 메인 스레드 점유
  • 우선순위 개념 없음
  • 한 번 시작한 렌더는 끝까지
  • Suspense / Concurrent 같은 기능 구현 자체가 어려움
Fiber Reconciler (React 16+)
  • 명시적 Fiber 트리 + 작업 큐
  • 작업 단위마다 yield 가능 → 입력/애니메이션 우선
  • 우선순위(Lane) 기반 스케줄링
  • 중단·재시도·폐기 지원
  • Concurrent / Suspense / Transitions / Streaming SSR 의 토대

"Fiber" 라는 이름의 유래

운영체제 용어인 *fiber*(스레드보다 작은 협력적 실행 단위) 에서 따왔습니다. 한 Fiber 노드는 한 컴포넌트 인스턴스에 대응하는 작업 유닛이며, React 가 다음에 무엇을 할지 결정하는 단위입니다.

핵심 통찰은 두 가지입니다. ① *작업을 쪼개라* — 한 번에 끝내지 말고 노드 단위로 처리한다. ② *작업을 데이터로 만들어라* — 콜 스택 대신 자료구조에 진행 상태를 둬야 멈췄다 다시 시작할 수 있다. 이 둘이 동시 만족되어야 우선순위·취소·재시도가 가능해집니다.

실무 적용

어떤 상황에서 사용하는가

검색창에 글자를 타이핑할 때마다 큰 결과 리스트가 다시 그려지면서 입력이 1~2 글자씩 끊긴다는 사용자 리포트가 들어왔다.

어떻게 적용하는가

(1) 입력 onChange 의 `setQuery` 는 그대로 두되, `setResults` 는 `startTransition` 으로 감싸 Transition Lane 에 보낸다. (2) 결과 영역은 `useDeferredValue(query)` 를 받아 입력보다 한 박자 늦게 갱신한다. (3) `<Suspense fallback={<Skeleton />}>` 으로 새 결과 도착 전 이전 결과를 유지한다. (4) Profiler 에서 입력 Lane 과 Transition Lane 의 commit 비율을 확인.

흔한 실수와 안티패턴

  • 모든 setState 를 startTransition 으로 감싸기 — 입력처럼 즉시 보여야 할 업데이트까지 미뤄지면 오히려 끊긴다.
  • Transition 안에서 `await` 후 `setState` 를 또 부르면 Transition 우선순위가 깨질 수 있음 — 한 사이클 내에서 처리.
  • Strict Mode 의 이중 렌더를 회피하려고 ref 에 부수효과를 숨기는 것 — 더 깊은 버그를 만든다.
  • `useLayoutEffect` 를 남용해 commit 동기 구간이 길어지면 Concurrent 의 이점을 잃는다.

흔한 오해

오해

"Fiber 는 Virtual DOM 의 또 다른 이름이다."

교정

Virtual DOM 은 개념, Fiber 는 그것을 구현하는 자료구조 + 스케줄러의 코드네임.

왜 중요

같은 Virtual DOM 개념이지만 Stack Reconciler 시절에는 Fiber 가 없었다. Fiber 의 핵심은 "작업 단위로 쪼개고 멈출 수 있게 한 것".

오해

"Render Phase 가 두 번 호출되는 건 React 18 버그다."

교정

Strict Mode + Concurrent 의 의도된 동작. 부수효과 버그를 노출하기 위한 검증 장치.

왜 중요

Concurrent 에서는 work-in-progress 가 실제로 폐기·재시도될 수 있어, 개발 시에도 같은 가정을 강제로 검증한다.

오해

"useTransition 은 그냥 debounce 다."

교정

debounce 는 호출 자체를 늦추지만, Transition 은 호출은 즉시 하되 *우선순위를 낮춰* React 가 양보·중단할 수 있게 한다.

왜 중요

입력 도중에도 결과 계산이 시작되되, 더 급한 일이 오면 폐기되고 다시 시작한다. 결과적으로 사용자에게 "막힘" 이 사라진다.

면접 질문

심화토스카카오네이버라인

답변 방향 힌트

"콜 스택 → 자료구조" 와 "작업 단위 분할" 두 축으로 답하세요.

반드시 언급할 키워드

  • Stack Reconciler: 재귀, 콜 스택이 진행 상태, 중단 불가
  • Fiber: 명시적 트리 + 포인터 순회 + 작업 단위로 분할
  • 진행 상태가 데이터(Fiber 노드의 flags/lanes) 로 표현됨
  • 단위마다 yield 가능 → 우선순위 기반 스케줄링
  • 두 트리(current/wip) 의 더블 버퍼링으로 중단 안전성 확보
  • 이게 Concurrent · Suspense · Streaming SSR 의 토대

예상 꼬리 질문

  • Lane 모델이 expirationTime 을 대체한 이유는 무엇인가요?
  • commit phase 는 왜 중단 가능하게 만들지 않았나요?

자기 점검

Fiber 노드에 두 트리가 alternate 로 존재하는 이유를 한 문장으로 답하라.

기대 키워드

중단폐기안전currentwork-in-progresscommit swap

자주 하는 오해

"성능 최적화" 로만 이해하면 부족하다. 두 트리는 Concurrent 에서의 *중단/재시도 안전성* 을 위한 더블 버퍼링이다.

입력 onChange 안에서 `setState` 두 개를 부르면 React 18 에서 몇 번 렌더되는가?

기대 키워드

automatic batching1 번한 사이클

자주 하는 오해

"두 번" 이라고 답하기 쉽지만, React 18 부터는 setTimeout/Promise/native event 어디서 호출하든 같은 tick 안의 setState 는 자동으로 묶여 한 번만 렌더된다.

Lane 모델이 expirationTime 을 대체한 이유 한 가지를 들어 보라.

기대 키워드

비트마스크여러 우선순위 동시표현력

자주 하는 오해

"더 빠르다" 가 아니라 *표현력* 이 핵심. 단일 숫자로는 "여러 우선순위가 동시에 펜딩" 같은 상태를 표현하기 어려웠다.

학습 자료