티스토리 뷰
Web Worker는 JavaScript의 멀티스레딩을 가능하게 해주는 브라우저 API입니다. 즉, 무거운 작업을 메인 스레드(UI 스레드)와 분리해서 실행할 수 있도록 해줍니다.
🔧 1. 왜 필요한가?
JavaScript는 단일 스레드(single-threaded) 언어입니다.
그래서 긴 루프, 대용량 계산, 데이터 파싱 등 무거운 작업을 실행하면 UI가 멈추거나 렌더링이 지연됩니다.
📌 이때 Web Worker를 사용하면:
- 무거운 연산을 백그라운드 스레드에서 처리
- UI는 끊김 없이 반응성 유지
🧠 2. 어떻게 작동하나?
Web Worker는 별도의 파일을 만들어서 사용하는 방식입니다.
main.js는 UI 스레드, worker.js는 백그라운드 스레드로 실행됩니다.
예시:
🔸 worker.js
// worker.js
self.onmessage = function (e) {
const result = e.data * 2;
self.postMessage(result);
};
🔸 main.js
const worker = new Worker("worker.js");
worker.onmessage = function (e) {
console.log("결과:", e.data);
};
worker.postMessage(10); // 백그라운드로 데이터 보냄
⚙️ 3. 주요 특징
항목 설명
| ✅ 장점 | - UI 멈춤 없이 연산 가능- 무거운 작업 분리 |
| ❌ 제한 | - DOM 접근 불가- alert, confirm 불가- 같은 출처(Same-origin policy) 파일만 접근 가능 |
| 📡 통신 | postMessage()와 onmessage를 통해 메시지로만 통신 |
| 🧵 종류 | - 일반 Worker- Shared Worker (여러 탭/스크립트에서 공유)- Service Worker (오프라인 캐시, 백그라운드 동기화 등 웹앱용) |
🔒 4. 주의사항
- 워커에서 사용 가능한 전역 객체는 self (window 아님)
- 워커는 별도의 파일이어야 하며, ESM 방식 (type="module")도 지원됨
- 메시지 기반이기 때문에 병렬 처리는 되지만 동기적인 데이터 접근은 어렵다 (WebAssembly가 더 적합할 수 있음)
🎯 사용 예시
- 이미지/영상 필터 처리
- 암호화/복호화 연산
- 대규모 데이터 파싱 (JSON, CSV)
- AI 모델 실행 (TensorFlow.js 등)
- 실시간 차트/그래프 계산
React에서 Web Worker를 사용하는 대표적인 예는 무거운 연산이나 대용량 데이터를 백그라운드에서 처리하여 UI를 멈추지 않도록 하는 것입니다. 아래 예시는 Web Worker를 React 컴포넌트에서 사용하는 기본적인 구조입니다.
✅ 예시: 숫자를 백그라운드에서 제곱하는 Worker
1. worker.js (Web Worker 파일)
// public/worker.js
self.onmessage = function (e) {
const num = e.data;
const result = num * num;
self.postMessage(result);
};
- self.onmessage: 메인 스레드로부터 메시지를 받았을 때 실행
- self.postMessage: 계산 결과를 메인 스레드로 전송
2. React 컴포넌트에서 Worker 사용
// App.jsx
import React, { useEffect, useRef, useState } from 'react';
function App() {
const [input, setInput] = useState(0);
const [result, setResult] = useState(null);
const workerRef = useRef(null);
useEffect(() => {
// Web Worker 생성 (public 폴더 기준 경로)
workerRef.current = new Worker('/worker.js');
// Worker로부터 메시지 받기
workerRef.current.onmessage = (e) => {
setResult(e.data);
};
// 컴포넌트 언마운트 시 Worker 종료
return () => {
workerRef.current.terminate();
};
}, []);
const handleCalculate = () => {
workerRef.current.postMessage(Number(input));
};
return (
<div style={{ padding: 20 }}>
<h2>React + Web Worker</h2>
<input
type="number"
value={input}
onChange={(e) => setInput(e.target.value)}
/>
<button onClick={handleCalculate}>제곱 계산</button>
<p>결과: {result}</p>
</div>
);
}
export default App;
💡 주요 포인트
항목 설명
| new Worker('/worker.js') | public 폴더 기준 경로 |
| postMessage(data) | Worker에 데이터 보내기 |
| onmessage | Worker로부터 결과 받기 |
| terminate() | 리소스 정리 (컴포넌트 종료 시) |
📦 Webpack + create-react-app에서 Worker 사용하기
CRA 기반에서는 직접 worker 파일을 불러올 수 없습니다.
이때는 worker-loader 또는 vite-plugin-worker, 혹은 custom webpack 설정이 필요합니다.
예시:
// import Worker from './myWorker.js?worker'
// const worker = new Worker();
?worker 쿼리는 Vite에서 worker로 번들링하겠다는 의미입니다.
✳️ 추천 사용 시나리오
- 실시간 대용량 차트 데이터 가공
- 이미지 처리 (ex. 필터링, 썸네일 생성)
- 복잡한 수학 계산 (ex. 피보나치, 소수 구하기)
- JSON 파일 등 대용량 데이터 파싱
React에서 Web Worker를 사용하는 예제를 아래에 제공합니다. 이 예제는 무거운 계산(예: 피보나치 수열)을 Web Worker로 분리해 UI 렌더링이 끊기지 않도록 하는 방식을 보여줍니다.
🧩 1. 프로젝트 구조
/src
├── App.tsx
├── worker.ts
└── custom.d.ts
📦 2. 설정 (TypeScript 환경)
✅ custom.d.ts
Web Worker를 TypeScript에서 사용하려면 타입 선언이 필요합니다.
declare module "*.worker.ts" {
const WorkerFactory: new () => Worker;
export default WorkerFactory;
}
🧠 3. Web Worker 코드 (worker.ts)
const ctx: Worker = self as any;
ctx.onmessage = (event) => {
const n = event.data;
const fib = (num: number): number =>
num <= 1 ? num : fib(num - 1) + fib(num - 2);
const result = fib(n);
ctx.postMessage(result);
};
- 무거운 피보나치 계산을 워커에서 처리.
- onmessage로 입력을 받고, 결과를 postMessage로 전달.
⚛️ 4. React 컴포넌트 (App.tsx)
import React, { useState, useEffect } from "react";
import Worker from "./worker.ts?worker"; // Vite/Webpack 5+에서 지원
const App: React.FC = () => {
const [number, setNumber] = useState(35);
const [result, setResult] = useState<number | null>(null);
const [worker] = useState(() => new Worker());
useEffect(() => {
worker.onmessage = (e) => {
setResult(e.data);
};
return () => {
worker.terminate(); // 컴포넌트 언마운트 시 종료
};
}, [worker]);
const handleClick = () => {
setResult(null);
worker.postMessage(number);
};
return (
<div className="p-4 text-lg">
<label>
피보나치 계산:
<input
type="number"
value={number}
onChange={(e) => setNumber(Number(e.target.value))}
className="border ml-2 w-20"
/>
</label>
<button onClick={handleClick} className="ml-4 px-3 py-1 bg-blue-500 text-white rounded">
계산 시작
</button>
<div className="mt-4">
{result === null ? "계산 중..." : `결과: ${result}`}
</div>
</div>
);
};
export default App;
⚙️ 5. 번들러 설정 (Vite/Webpack)
- Vite는 ?worker 쿼리를 지원하므로 추가 설정 없이 사용 가능.
- Webpack을 쓸 경우 worker-loader 설치가 필요:
npm install worker-loader --save-dev
// webpack.config.js
module: {
rules: [
{
test: /\.worker\.ts$/,
use: { loader: "worker-loader" },
},
],
},
✅ 요약
항목 설명
| worker.ts | 백그라운드 작업 로직 (계산, 파싱 등) |
| App.tsx | Web Worker와 메시지 통신 처리 |
| ?worker or worker-loader | 모듈로 Worker 로드 |
| useEffect | 메시지 핸들링 및 정리(clean-up) |
🧠 실전 활용 예
- 이미지 필터 처리 (예: canvas 작업)
- 실시간 마켓 차트 계산
- WebAssembly와 연동된 대규모 수치 연산
- JSON 대량 파싱 (특히 모바일에서)
필요하면 해당 예시도 자세히 도와드릴 수 있어요.
'Skill > html js css' 카테고리의 다른 글
| Invariant Violation: Expected drag drop context (0) | 2025.07.19 |
|---|---|
| 클라이언트가 저장한 쿠키를 읽으려면 (1) | 2025.07.17 |
| React.memo와 useMemo (0) | 2025.06.24 |
| react] typescript: field as keyof typeof updated[number] (1) | 2025.06.23 |
| js] Spread Syntax (0) | 2025.02.24 |
- Total
- Today
- Yesterday
- lombok
- object key
- $.each
- border-collapse
- @ExceptionHandler
- 프로젝트명변경
- 여러 컬럼 update
- Javascript
- springboot
- draw.io
- 전후방탐색
- oracle
- spring
- JQuery
- excel
- QueryDSL
- PostgreSQL
- ul li로 테이블
- 정규식
- CSS
- element위치
- devtools
- DatePicker
- getter
- sumifs
- setter
- $.extend
- 진열사랑
- caniuse
- Keycode
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
