React 스케줄러(스케줄링 엔진)

React 스케줄러는 병렬 처리 기능의 핵심 구성 요소로, 브라우저에서 작업을 효율적으로 관리하는 데 사용됩니다. 이 시스템은 React 자체와 분리되어 있으며, 다양한 작업을 우선순위에 따라 분할하고 실행하는 데 초점을 맞추고 있습니다.

1. 스케줄러의 역할과 필요성

주요 문제: 자바스크립트는 단일 스레드로 동작하며, 대규모 렌더링 작업은 메인 스레드를 차지해 UI 응답성을 저하시킬 수 있습니다.

스케줄러의 기능: 작업을 작은 단위로 나누어 브라우저의 공백 시간에 분산 실행함으로써 메인 스레드를 차지하지 않도록 설계되었습니다. 이는 사용자 경험을 원활하게 유지하는 데 기여합니다.

비유:

  • 스케줄러 없음: 큰 요리 준비 시 모든 단계를 연속적으로 수행해야 하며, 전화 받기 등 중단이 불가능합니다.
  • 스케줄러 있음: 요리 과정을 채소 준비, 조리 등으로 분할하여 중간에 전화를 받거나 문을 열 수 있습니다.

2. 핵심 메커니즘

1. 작업 우선순위 관리

스케줄러는 작업을 우선순위에 따라 분류합니다. 예를 들어:

  • 즉시 실행: 사용자 입력과 같은 고우선순위 작업
  • 일반 실행: 네트워크 요청 완료 후 업데이트
  • 저우선순위: 데이터 분석과 같은 배경 작업

2. 타임슬라이싱 기술

이 기술은 긴 작업을 약 5ms 단위의 작은 단위로 분할합니다. 실행 중에는 현재 프레임의 남은 시간을 확인하고, 시간이 부족할 경우 작업을 일시 중단합니다. 다음 프레임에서 이 작업을 재개합니다.

// 단순화된 타임슬라이싱 예시
function executeTask(timeLimit) {
  while (currentJob && !checkTimeLimit(timeLimit)) {
    currentJob = processNode(currentJob);
  }
  
  if (currentJob) {
    scheduleNextTask(executeTask);
  }
}

function checkTimeLimit(limit) {
  return Date.now() - startTime >= limit;
}

3. 작업 스케줄링 알고리즘

우선순위에 따라 작업을 관리하는 큐 구조를 사용합니다. 새로운 작업이 추가되면 해당 우선순위에 맞게 큐에 저장되며, 최고 우선순위 작업부터 실행됩니다. 고우선순위 작업이 도중에 추가되면 현재 실행 중인 작업은 중단되고 다시 시작됩니다.

3. React와의 통합 방식

1. 작업 분류

React는 다양한 업데이트를 우선순위에 따라 분류합니다:

  • 사용자 입력: 고우선순위
  • 데이터 업데이트: 일반 우선순위
  • Suspense 전환: 저우선순위

2. 스케줄링 진입점

상태 변경 시 React는 즉시 렌더링하지 않고 작업을 스케줄러에 제출합니다:

// 간단한 스케줄링 프로세스
function queueUpdate(fiber, priority) {
  const task = {
    handler: () => processConcurrentRoot(fiber),
    level: priority,
  };
  
  scheduleTask(task);
}

3. 중단 가능한 렌더링

Fiber 구조를 통해 렌더링 작업이 여러 단위로 나뉘어 실행되며, 중간에 작업을 중단할 수 있습니다:

function processNode(fiber) {
  // 현재 노드 처리
  
  if (checkYield()) {
    return fiber; // 다음 번에 이 위치에서 계속 실행
  }
  
  // 자식 노드 처리
}

4. 실제 적용 사례

1. startTransition 사용

이 함수는 작업 우선순위를 낮춥니다:

setInputValue(input);
startTransition(() => {
  setSearchQuery(input);
});

2. useDeferredValue 활용

값 업데이트를 저우선순위로 처리하여 중간 상태를 무시하고 최신 값만 렌더링합니다.

3. Suspense 사용

데이터 로딩 중에는 페일백 UI를 표시하고, 데이터가 준비되면 실제 콘텐츠로 전환합니다.

5. 기술적 구현 세부사항

1. requestIdleCallback 사용 제외 이유

  • 실행 주기 제한 (초당 20회)
  • 호환성 문제
  • 정밀한 제어 필요성

2. 모의 구현

다양한 API를 사용해 작업을 스케줄링합니다:

  • 고우선순위: MessageChannel
  • 저우선순위: setTimeout
// 간단한 채널 구현
const channel = new MessageChannel();
channel.port1.onmessage = executeWork;

function scheduleWork(callback) {
  scheduledCallback = callback;
  channel.port2.postMessage(null);
}

요약

React 스케줄러는 작업 우선순위 관리, 타임슬라이싱, 중단 및 재개 기능을 통해 병렬 렌더링을 가능하게 합니다. 이 시스템은 복잡한 계산 작업에서도 UI 응답성을 유지할 수 있도록 설계되었습니다.

사용자 입력 → React 업데이트 생성 → 스케줄러에 작업 제출(우선순위 포함) → 
→ 우선순위 큐에 저장 → 타임슬라이싱 실행 → 
→ 시간 제한 확인 → 초과? → 메인 스레드 반환 → 다음 프레임 재개
                              ↓
                              아니오 → 작업 완료 시까지 계속 실행

태그: React Concurrent Mode Fiber Task Scheduling Priority Queue

6월 20일 04:39에 게시됨