티스토리 뷰

Skill/html js css

web worker

진열사랑 2025. 7. 14. 23:39

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 대량 파싱 (특히 모바일에서)

필요하면 해당 예시도 자세히 도와드릴 수 있어요.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/01   »
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
글 보관함