카테고리 없음

Javascript worker와 blob(동적 코드 주입)

JUNFUTURE 2026. 3. 31. 11:00

들어가며

아래 코드를 이해해보자

// 1. 워커에서 실행될 코드를 문자열로 정의 (템플릿 리터럴 활용)
const workerCode = `
  self.onmessage = function(e) {
    console.log('[Worker] Received data from main thread:', e.data);
    
    // 무거운 연산을 시뮬레이션 (메인 스레드 방해 없음)
    const result = e.data * e.data;
    
    // 결과를 다시 메인 스레드로 전송
    self.postMessage(result);
  };
`;

// 2. 문자열을 Blob 객체로 변환 (타입은 반드시 javascript)
const blob = new Blob([workerCode], { type: 'application/javascript' });

// 3. Blob을 가리키는 고유한 URL 생성
const blobURL = URL.createObjectURL(blob);
console.log('[Main] Created Blob URL:', blobURL);

// 4. 생성된 URL을 사용하여 워커 인스턴스 생성
const myWorker = new Worker(blobURL);

// 5. 워커로부터 오는 메시지를 처리할 핸들러 등록
myWorker.onmessage = function(e) {
  console.log('[Main] Worker computed result:', e.data);
  
  // 6. 사용이 끝난 URL은 메모리 해제를 위해 폐기 (중요!)
  URL.revokeObjectURL(blobURL);
  console.log('[Main] Blob URL has been released from memory.');
};

// 7. 워커에게 작업 지시 (데이터 전송)
console.log('[Main] Sending 10 to the worker.');
myWorker.postMessage(10);

 

Worker

worker는 js 파일을 받아서 실행해준다. 정확히 말하면 worker는 "Worker Thread"의 개념이다.

woker가 등장하게된 배경은 브라우저의 main thread와 분리되어 서로 다른 context에서 데이터를 주고받으며 js를 실행하기위함이다.

 

브라우저의 main thread는 UI를 담당한다. window, document(DOM) 접근을 관리하고

worker thread는 이외에 백그라운드 연산(당연히 다른 .js 코드 실행을 뜻한다)을 수행한다.

 

이때 둘 thread 간의 통신이 필요할텐데, 오직 message를 이용해서만 통신을 하고 이때 아래와 같은 핸들러들을 이용해서 통신하는 것이다.

 

Worker - Main thread 통신 규격 (Event driven)

보낼 때 : postMessage(data)

받을 때 : onmessage 이벤트 핸들러

const myWorker = new Worker('worker.js');

// 1. 워커가 나에게 보낸 메시지를 받을 준비
myWorker.onmessage = function(event) {
    console.log("워커가 보낸 답장:", event.data);
};

// 2. 워커에게 메시지 던지기
myWorker.postMessage("안녕 워커!");

 

worker를 생성하는 쪽(main thread)에서는 반드시 위와 같은 코드가 필요할 것이다.

 

생성되는 worker의 코드는 아래와 같은 패턴이 있을 것이다.

// 3. 메인이 보낸 메시지를 받을 준비 (자신을 가리키는 self 사용)
self.onmessage = function(event) {
    const receivedData = event.data;
    console.log("메인이 보낸 내용:", receivedData);

    // 4. 메인에게 다시 답장 던지기
    const reply = "받았다: " + receivedData;
    self.postMessage(reply); 
};

 

worker 코드 내부에 self??

(TBD)

 

Blob (Binary large object)

메모리 내부에 존재하는 바이너리 데이터다.

MIME 타입

C도 많이 해봤으면 알듯이 메모리에 저장된 데이터를 어떻게 해석할까?의 문제를 해결해주는게 바로 MIME 타입이다.

그러니까... 이런식으로 blob을 정의 한다는 건 쌩짜로 바이너리 데이터 넣는거니까 이걸 브라우저에서 뭐 어떤 데이터 인지 알아야 이걸 처리(렌더링) 할테니까, 타입을 알려주는게 필요하다.

아래에서 workerCode는 위에서 봤던 self.onmessage로 시작하는 코드 일 것이다.

const blob = new Blob([workerCode], { type: 'application/javascript' });
MIME 타입(Multipurpose Internet Mail Extensions)은 파일의 성격과 형식을 나타내는 식별자로, type/subtype 구조(text/html, image/png 등)로 웹에서 데이터 형식을 정의합니다. 주로 HTTP 헤더(Content-Type)를 통해 서버가 브라우저에게 파일 종류를 알리고, 브라우저는 이에 따라 파일을 랜더링하거나 다운로드한다.
text/html: HTML 문서
image/png: PNG 이미지
application/json: JSON 데이터
application/javascript: 자바스크립트 파일​

 

URL.createObjectURL(blob)

blob:https://현재도메인/무작위-UUID 형태의 가짜 주소를 생성하고,

이 주소가 현재 내 컴퓨터 RAM의 특정 지점(Blob 데이터가 있는 곳 - 주소, URL)을 가리키도록 연결

const blobURL = URL.createObjectURL(blob);

 

Blob을 이용한 동적 js 코드 주입

// 정적으로 코드 주입(code injection)
const myWorker = new Worker('worker.js');
// 동적으로 코드 주입(code injection)
const workerCode = `
  self.onmessage = function(e) {
    console.log('[Worker] Received data from main thread:', e.data);
    
    // 무거운 연산을 시뮬레이션 (메인 스레드 방해 없음)
    const result = e.data * e.data;
    
    // 결과를 다시 메인 스레드로 전송
    self.postMessage(result);
  };
`;

const blob = new Blob([workerCode], { type: 'application/javascript' });
const blobURL = URL.createObjectURL(blob);
const myWorker = new Worker(blobURL);