cd ../
Frontend·2026-05-12·5 min read·# entry/040

React의 렌더링 우선순위: Fiber와 Lane 모델

input 하나로 10,000개 항목을 필터링할 때 왜 타이핑이 버벅일까? Stack Reconciler의 한계부터 Fiber 아키텍처, Lane 모델, Event-to-Priority 매핑까지 React 우선순위 시스템을 정리합니다.

React는 UI의 부드러운 반응성을 보장하기 위해 작업마다 '우선순위'를 부여하고, 더 중요한 작업이 들어오면 진행 중인 작업을 중단할 수 있도록 설계되어 있습니다.

사용자 입력은 즉시 처리하고, 화면에 당장 보이지 않는 작업은 나중에 처리한다. React의 우선순위 시스템은 이 단순한 원칙을 구현합니다.


어떤 상황에서 문제가 생기는가

input 하나로 10,000개 항목을 필터링하는 시나리오를 생각해봅니다.

const [query, setQuery] = useState("");
const filtered = items.filter((item) => item.includes(query)); // 10,000개 순회

return (
  <>
    <input onChange={(e) => setQuery(e.target.value)} />
    {filtered.map((item) => (
      <Item key={item} value={item} />
    ))}
  </>
);

일반적인 동기 렌더링에서는 키를 누를 때마다 10,000개 컴포넌트가 리렌더됩니다. 브라우저는 이 작업이 끝날 때까지 다음 키 입력을 처리하지 못하고, 사용자는 타이핑이 지연되는 것처럼 느낍니다.

React의 우선순위 시스템은 이 문제를 해결하기 위해 만들어졌습니다.


기술적 유래: Stack Reconciler에서 Fiber로

과거 React의 Stack Reconciler 방식은 한 번 렌더링을 시작하면 끝날 때까지 멈출 수 없는 동기 구조였습니다.

Stack Reconciler (React 15 이하)

렌더링 시작 → ... → 렌더링 완료
         ↑ 이 구간은 중단 불가
         ↑ 사용자 클릭, 타이핑 모두 대기
Jank 현상

리스트 10,000개 렌더링이 시작되면 브라우저는 그 작업을 마칠 때까지 사용자의 클릭과 타이핑을 처리하지 못합니다. 화면이 멈추는 Jank 현상과 프레임 드롭의 주 원인이었습니다.

React 팀은 렌더링 작업을 잘게 쪼개고, 작업마다 중요도를 부여해 가로채기(Interruption) 가 가능한 구조를 설계했습니다. 이것이 2017년 React 16에 도입된 Fiber 아키텍처입니다.

Fiber (React 16+)

작업 A 시작 → [중단 가능 지점] → 고우선순위 작업 B 등장
  → B 먼저 처리 → A 재개 → 완료

우선순위의 핵심 메커니즘: Lane 모델

React 18부터는 Lane 모델을 사용해 우선순위를 관리합니다. 32비트 정수를 활용해 각 작업이 어떤 '차선'을 달릴지 결정하는 방식입니다.

Lane 모델의 장점
  • 각 업데이트에 32개 비트 중 하나 이상을 할당 - 숫자가 작을수록 우선순위가 높음 - 여러 낮은 우선순위 작업을 비트 연산으로 묶거나 분리 가능 - 특정 작업만 골라서 먼저 처리하는 세밀한 스케줄링 가능
과거 방식의 한계
  • 단순 숫자 비교 방식 - 작업을 묶거나 분리하는 유연성이 부족 - 복잡한 동시성 패턴을 표현하기 어려움

우선순위 Level

React 스케줄러는 다섯 단계의 우선순위를 정의합니다.

Level이름해당 작업
1Immediate이벤트를 처리하는 동안 발생하는 업데이트
2UserBlocking클릭, 입력에 의한 상태 변화
3Normal네트워크 응답, 데이터 로딩
4Low분석 도구 로깅, 백그라운드 작업
5Idle화면에 보이지 않는 컴포넌트 렌더링
숫자가 작을수록 긴급하다

Immediate(1)가 가장 높은 우선순위입니다. Idle(5)은 시스템이 한가할 때만 처리됩니다.


React의 Default 우선순위

개발자가 명시적으로 지정하지 않아도, React는 어떤 이벤트가 업데이트를 발생시켰느냐 에 따라 자동으로 우선순위를 결정합니다.

Event-to-Priority 매핑

사용자의 명확한 의도가 담긴 개별적 클릭과 입력입니다.

  • 해당 이벤트: click, mousedown, keydown, touchstart
  • 우선순위: Immediate (즉시 처리)
왜 가장 높은가

버튼을 눌렀는데 화면이 즉각 반응하지 않으면 사용자는 앱이 고장났다고 느낍니다.


기아 상태 방지: 5초 규칙

우선순위가 낮은 작업은 계속 밀릴 수 있습니다. React는 이를 방지하기 위해 각 우선순위에 만료 시간을 설정합니다.

NormalPriority 만료 시간: ~5,000ms

0ms ─────────────────────────── 5,000ms
               ↑
       이 구간 동안 계속 뒤로 밀림
               ↑
       5초 초과 시 → Immediate로 격상 → 강제 렌더링
왜 5초인가

특정 작업이 무한히 밀리는 기아(Starvation) 상태를 방지하기 위한 설계입니다. 아무리 우선순위가 낮더라도 5초가 지나면 즉시 처리됩니다.

우선순위별 만료 시간
우선순위만료 시간
Immediate즉시 (만료 없음)
UserBlocking250ms
Normal5,000ms
Low10,000ms
Idle만료 없음 (시스템이 한가할 때만)

정리

React의 우선순위 시스템은 세 가지 개념이 맞물려 동작합니다.

  1. Fiber 아키텍처 — 렌더링 작업을 중단·재개 가능한 단위로 분해
  2. Lane 모델 — 비트 연산으로 작업의 우선순위와 묶음을 유연하게 관리
  3. Event-to-Priority 매핑 — 이벤트 종류에 따라 자동으로 우선순위 결정

startTransition이나 useDeferredValue 같은 React 18의 동시성 API는 이 시스템 위에서 동작합니다. 개발자가 직접 "이 업데이트는 낮은 우선순위"라고 React에 알려주는 방법입니다.