Files
2nd/10_Wiki/Topic_Programming/Coding/Web_OffMain_WebWorker.md
T
Antigravity Agent 9148c358d0 docs(10_Wiki): 위키 전체 재구성 — Topic_* 폴더를 4개 카테고리로 통합 + 대규모 중복 제거
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를
Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류.

- 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로
  자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거,
  동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거.
- 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming,
  Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business,
  Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로,
  나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는
  title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백).
  원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지.
- 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서.
- 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는
  지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지.
- Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경.
- 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
2026-07-05 00:33:48 +09:00

5.7 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
web-offmain-webworker Web Worker / Comlink — main thread 비우기 Coding draft B conceptual 2026-05-09 2026-05-09
web
worker
performance
vibe-coding
language applicable_to
TS
Frontend
Web Worker
Service Worker
SharedArrayBuffer
Comlink
transferable
OffscreenCanvas

Web Worker

Browser 도 main thread block = INP / jank. 무거운 JS = Web Worker. Comlink 가 RPC wrap. OffscreenCanvas 가 worker 에서 그림. SharedArrayBuffer 가 zero-copy.

📖 핵심 개념

  • Web Worker: 별 thread, postMessage 통신.
  • Service Worker: 다름 — 네트워크 인터셉트 (위 PWA).
  • Shared Worker: 여러 tab 공유.
  • OffscreenCanvas: 캔버스 그림 worker 에서.

💻 코드 패턴

단순 worker

// worker.ts
self.onmessage = (e) => {
  const { data } = e;
  const result = heavyComputation(data);
  self.postMessage(result);
};

// main.ts
const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
worker.onmessage = (e) => console.log('result:', e.data);
worker.postMessage({ items: [...] });
// worker.ts
import * as Comlink from 'comlink';

class HeavyAPI {
  async process(items: number[]): Promise<number> {
    return items.reduce((s, x) => s + x * x, 0);
  }
  async fft(samples: Float32Array): Promise<Float32Array> { ... }
}

Comlink.expose(new HeavyAPI());
// main.ts
import * as Comlink from 'comlink';
import type { HeavyAPI } from './worker';

const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
const api = Comlink.wrap<HeavyAPI>(worker);

const sum = await api.process([1, 2, 3]);

→ promise 기반 RPC, type-safe.

Vite worker import

import HeavyWorker from './worker?worker';
const worker = new HeavyWorker();

Transferable (zero-copy)

const buf = new ArrayBuffer(10_000_000);
worker.postMessage({ buf }, [buf]);
// buf 는 main 에서 더 사용 못 함 — transferred

→ 큰 데이터 빠르게.

SharedArrayBuffer (양방향 공유)

// Cross-origin isolation 필요
// Response headers:
//   Cross-Origin-Opener-Policy: same-origin
//   Cross-Origin-Embedder-Policy: require-corp

const sab = new SharedArrayBuffer(1024);
const view = new Int32Array(sab);

worker.postMessage({ sab });
// worker 와 main 이 같은 메모리

Atomics.store(view, 0, 42);
const v = Atomics.load(view, 0);
Atomics.wait(view, 0, 0);    // block 까지 변경
Atomics.notify(view, 0, 1);   // 깨우기

OffscreenCanvas

// main
const canvas = document.getElementById('c') as HTMLCanvasElement;
const offscreen = canvas.transferControlToOffscreen();
worker.postMessage({ canvas: offscreen }, [offscreen]);
// worker
self.onmessage = (e) => {
  const ctx = e.data.canvas.getContext('2d');
  // 그림 — main thread 영향 X
};

→ 게임 / 차트 / 이미지 처리.

Use case

- 큰 JSON parse
- 이미지 / 비디오 처리 (Sharp, FFmpeg.js)
- 압축 / 암호화 (gzip, AES)
- ML inference (ONNX Runtime Web, TF.js)
- PDF generation
- Crypto / hashing

React 통합

function useWorker<T, R>(input: T): R | null {
  const [result, setResult] = useState<R | null>(null);
  
  useEffect(() => {
    const worker = new Worker(new URL('./worker.ts', import.meta.url), { type: 'module' });
    worker.onmessage = (e) => setResult(e.data);
    worker.postMessage(input);
    return () => worker.terminate();
  }, [input]);
  
  return result;
}

또는 Comlink + useEffect:

const apiRef = useRef<Remote<HeavyAPI>>();

useEffect(() => {
  const w = new Worker(...);
  apiRef.current = Comlink.wrap(w);
  return () => w.terminate();
}, []);

Pool (여러 worker 병렬)

class WorkerPool {
  private workers: Worker[] = [];
  private idle: Worker[] = [];
  private queue: { task: any; resolve: (v: any) => void }[] = [];

  constructor(size: number) {
    for (let i = 0; i < size; i++) {
      const w = new Worker(...);
      w.onmessage = (e) => {
        // 결과 전달 + idle 로
        const { resolve } = this.activeMap.get(w)!;
        resolve(e.data);
        this.idle.push(w);
        this.processQueue();
      };
      this.workers.push(w);
      this.idle.push(w);
    }
  }

  run(task: any): Promise<any> {
    return new Promise((resolve) => {
      this.queue.push({ task, resolve });
      this.processQueue();
    });
  }
  // ...
}

또는 piscina-browser 같은 라이브러리.

TypeScript 설정

// tsconfig.worker.json
{
  "compilerOptions": {
    "lib": ["ES2022", "WebWorker"],
    "module": "ESNext"
  }
}

Web Worker 한계

  • DOM access X.
  • 일부 API X (storage 일부, alert).
  • main 보다 setup 비용.

🤔 의사결정 기준

작업 추천
< 50ms main thread
50-500ms Worker (Comlink)
> 500ms Worker pool
큰 array SharedArrayBuffer (가능)
Canvas 그림 OffscreenCanvas worker
ML inference Worker + WASM / WebGPU
Cross-tab 공유 state Shared Worker + Broadcast Channel

안티패턴

  • Worker 매번 새로: setup 비싸. Pool / 재사용.
  • postMessage 큰 객체 deep clone: 느림. transferable.
  • DOM access in worker: 안 됨.
  • Worker 안 import 큰 dep: bundle 큰. tree-shake.
  • Comlink 매 호출 생성: 한 번 wrap.
  • SharedArrayBuffer 가정 + COOP/COEP 없음: undefined.
  • Termination 안 함: leak.

🤖 LLM 활용 힌트

  • Comlink 가 RPC + type 안전.
  • Vite/Webpack worker import 자연.
  • 큰 data = transferable, 양방향 = SAB.

🔗 관련 문서