React 우선순위, Lane

KB LEE·2025년 3월 24일
0

React Core

목록 보기
1/2

목적

React v16.14이후 업데이트된 업데이트 우선순위 관리에 대한 변경점을 알아보기

기존 구조의 문제점

1. CPU bound Task 블로킹

기존엔 update를 Expiration Time을 기준으로 우선순위, 배치여부를 관리했습니다.
=> Expiration Time에서는 렌더링 대상의 우선순위를 기준으로 같거나 큰 업데이트만 렌더링 대상에 포함되어 배치처리

React 16부터 본격적으로 Concurrent Mode가 실험적으로 구현되면서, 상태 업데이트를 긴급과 지연 정도로만 구분하기엔 한계가 있었습니다
=> Suspense로 인해 IO-Bound라는 개념이 추가되면서 생긴 이슈

Expiration Time Model에서는 현재 batch에 Task를 포함할지 여부를 결정하기 위해 상대적인 우선순위를 비교할 때 아래와 같은 비교를 진행합니다.

const isTaskIncludedInBatch = priorityOfTask >= priorityOfBatch;

해당 방식은 우선순위가 낮은 작업은 해당 작업보다 우선순위가 높은 작업이 수행된 이후에만 수행될 수 있는 제약이 있습니다.
예를 들어, Task A, B, C의 우선순위가 A > B > C 라면 A작업이 수행되어야지만 나머지 후순위 작업을 진행할 수 있습니다.

해당 방식은 Suspense가 등장하기 전에 설계되기 전까지는 문제가 없었습니다.
왜냐하면 모든 작업이 CPU bound이기 때문에 작업별 우선순위를 지켜 수행해야할 필요성이 낮기 때문입니다.

Q. What is “CPU bound”, “IO bound“?
A.
CPU-bound
계산 및 데이터처리 등 CPU연산에 집중되어 있어 CPU리소스를 많이 소비하는 작업, 대부분의 연산은 “CPU bound”로 처리됨 ( 렌더링을 포함 )
IO-bound
네트워크 요청, 파일 입출력 등 외부 자원과의 입출력 작업에 의존하는 작업

하지만 Suspense와 같은 IO bound Task을 도입하면서 우선순위가 높은 IO bound Task가 우선순위가 낮은 CPU bound Task를 막는 경우가 생겼습니다

Q. 왜 “CPU bound”의 작업을 막으면 안되나요?
A. IO bound Task을 대기하는 동안 필수적인 CPU bound Task(렌더링과 관련된 연산)를 막는다면 사용자 경험이 떨어지게 됩니다.

2. 우선순위 그룹의 표현이 제한적

그리고 또 다른 문제는 “우선순위 그룹의 표현에 제한적이다”는 것 입니다.

Set객체를 이용한 Expiration Time Model은 메모리 관리측면에서 비효율적이기때문에 우선순위를 그룹화하여 표현하려고 했습니다.

하지만 그마저도 아래 표현과 같이 제약적입니다.

const isTaskIncludedInBatch = taskPriority <= highestPriorityInRange && taskPriority >= lowestPriorityInRange;

해결책

Lane 모델이란?

LaneReact v16.14이후부터 도입된 내부 우선순위 관리 기법으로, 여러 종류의 업데이트를 비트마스크 형태로 표현

React 18부터는 훨씬 세분화된 Lane 시스템으로 Concurrent Mode에서 일어나는 다양한 종류의 업데이트를 더 효율적으로 스케줄링하고 병합

Lane 모델의 장점

  1. Task별 우선순위 설정을 Task Batching과 분리
    • “Task A가 Task B보다 우선순위가 높은가?”에 대한 개념과 “Task A는 현재 Task Group에 속하는가?”를 분리
  2. Lane은 32-bit data type으로 여러 Task를 표현할 수 있음

Lane 모델의 요소

Lane

  • Task를 나타내는 비트마스크의 유형을 Lane, 단일 비트가 활성화된 상태
  • setState를 통해 schedule된 업데이트를 포함하고, 이전의 update.expirationTime 필드를 대체

Lanes

  • batch를 나타내는 비트마스크의 유형을 Lanes, 0개 이상의 비트가 활성화된 비트마스크
  • Lanes, childLanes로 여러 업데이트를 관리하던 fiber.expirationTimefiber.childExpirationTime을 대체

특징

  • 숫자가 작을수록 우선순위가 높음
  • 여러 Lane을 동시에 활성화할 수 있음
    • Fiber가 현재까지 쌓인 모든 Lane을 가지고 있어야지만 React가 렌더링 과정에서 해당 Fiber가 처리해야 할 (우선) 작업이 있는지를 판단 가능
  • opaque type이며 ReactFiberLane 모듈에서만 비트마스크를 조작할 수 있음

변경점 및 PR 개요

기존 ReactFiberExpirationTime.js을 삭제하고, ReactFiberLane.js으로 업데이트

  • 대부분의 Expiration Time 필드는 Lane 모델로 변환
    [출처]: 대체된 필드

정리

  • 이전엔 만료시간을 기반으로 한 간단한 우선순위만 있었지만, React 18부터 Lane을 통해 여러 레벨을 세밀하게 관리
  • LaneReact 18에서 정식으로 도입된, 우선순위를 비트마스크로 표현하는 내부 메커니즘

참고자료

React 18 톺아보기 - 02. Lane 모델 | Deep Dive Magic Code
What is "Lane" in React?
Initial Lanes implementation by acdlite · Pull Request #18796 · facebook/react

profile
한 발 더 나아가자

0개의 댓글