"매 single thread 매 JS, layout, paint, event 매 모두 처리". 매 50ms+ task — 매 long task — 매 jank/INP 악화. 매 해결 = 매 break up + Web Worker (CPU) + scheduler.yield (cooperative) + offscreen canvas (rendering).
매 핵심
매 main thread 책임
JavaScript 실행.
Style 계산.
Layout (reflow).
Paint.
Composite 매 일부 (대부분 GPU).
Event dispatching.
rAF callbacks.
매 long task
>50ms task — Lighthouse "long task" — 매 user input 차단.
TBT (Total Blocking Time) — long task time 합산.
INP (Interaction to Next Paint, 2024 Web Vital) — 매 main thread block 매 직접 영향.
매 yielding 전략
setTimeout(fn, 0) — 매 macrotask — 매 input priority 의 X.
requestIdleCallback — 매 idle 만 — 매 best effort.
scheduler.postTask (priority) — 매 modern.
scheduler.yield() (Chrome 129+) — 매 explicit yield + continue.
MessageChannel postMessage — 매 lower latency.
Web Worker — 매 다른 thread — 매 CPU heavy.
OffscreenCanvas — 매 worker 매 렌더링.
매 응용
Heavy parsing (CSV, JSON 매 수십 MB).
ML inference (TensorFlow.js — Worker).
Image processing — OffscreenCanvas.
List rendering — virtualization + chunking.
💻 패턴
Long task break up — scheduler.yield
asyncfunctionprocessItems(items){for(constitemofitems){process(item);if(navigator.scheduling?.isInputPending()||performance.now()-lastYield>50){awaitscheduler.yield();// 매 main thread 풀어줌
lastYield=performance.now();}}}
// main
constcanvas=document.querySelector('canvas');constoffscreen=canvas.transferControlToOffscreen();worker.postMessage({canvas:offscreen},[offscreen]);// worker
self.onmessage=e=>{constctx=e.data.canvas.getContext('2d');functionframe(){ctx.fillRect(...);requestAnimationFrame(frame);}frame();};
import{useTransition}from'react';const[isPending,startTransition]=useTransition();constonChange=e=>{setQuery(e.target.value);// 매 urgent
startTransition(()=>{setResults(filter(e.target.value));// 매 interruptible
});};