서로 다른 실행 컨텍스트 간 데이터 전달 개념과 구조적 복사 동작 원리 요약

Web Worker와 Service Worker 메시지 비교(통신 대상·응답 방식·용도) 및 Transferable(ArrayBuffer) 활용 예시 포함

메시지 기반 설계 패턴(type 기반 프로토콜·상태 분리)과 실무 코드 샘플

워커 통신 아키텍처 설계 팁 제공


목차

  1. 메시지의 개념
  2. Web Worker과 Service Worker 메시지 비교
  3. 메시지를 쓰는 이유
  4. 메시지에 담을 수 있는 것
  5. 구조적 복사(Structured Clone) 개념
  6. Web Worker에서의 메시지 흐름
  7. Service Worker에서의 메시지 특징
  8. 메시지 vs API 호출 비교
  9. 핵심
  10. 메시지의 패턴 - 설계

메시지

개념

  • 서로 다른 실행 컨텍스트(스레드/워커/페이지) 사이에서 데이터를 주고 받기 위한 통신 단위
  • 이벤트 기반 데이터 전달
  • 브라우저 내부에서
    • 데이터 직렬화
    • 워커 쪽으로 전달
    • 이벤트로 수신

Web Worker / Service Worker 메시지 비교

구분 Web Worker 메시지 Service Worker 메시지

통신 대상 메인 스레드 ↔ 워커 페이지 ↔ 서비스 워커
기본 메커니즘 postMessage + message 이벤트 postMessage + message 이벤트
호출 방식 함수 호출 ❌ 함수 호출 ❌
전달 형태 데이터 객체 데이터 객체
동작 모델 이벤트 기반 비동기 이벤트 기반 비동기
응답 방식 이벤트로 응답 이벤트로 응답
네트워크 대체 가능 일부 가능(fetch 대체)
주요 용도 계산 결과 전달 상태 알림, 명령 전달

메시지를 쓰는 이유

이유 설명

실행 컨텍스트 분리 워커는 메인 스레드와 메모리 공간이 다름
동기 호출 불가 서로 직접 함수 호출 불가
안전성 스레드 간 데이터 충돌 방지
구조 단순화 명확한 요청/응답 패턴

메시지에 담을 수 있는 것

  • 가능 : 문자열, 숫자, 객체(JSON), 배열, ArrayBuffer
  • 불가능 : 함수, DOM 노드, 클래스 인스턴스(일반적으로)

구조적 복사(Structured Clone) 개념

  • 메시지는 구조적 복사 알고리즘으로 전달 됨
  • 특징
    • 기본 동작 : 데이터 복사해서 전달
    • 참조 공유 : X
    • 원본 수정 영향 : X
    • 비용 : 데이터 크기가 클 수록 증가
  • 예외
    • ArrayBuffer 등은 Transferable 로 전달 가능
      • 복사 X, 소유권 이동 가능 (빠름)

Web Worker에서의 메시지 흐름

  1. 메인 스레드가 “이 데이터 계산해 줘” 메시지 전송
  2. 워커가 message 이벤트 수신
  3. 워커가 계산 수행
  4. 결과를 메시지로 다시 전송
  5. 메인 스레드가 결과 수신 후 UI 반영

Service Worker에서의 메시지 특징

항목 설명

대상 다수 여러 탭/페이지와 통신 가능
식별 필요 어떤 클라이언트인지 구분 필요
용도 상태 전달, 명령 전달
주력 역할 메시지보다 fetch 이벤트가 핵심

메시지 vs API 호출 비교

구분 메시지 API 호출

범위 브라우저 내부 네트워크
지연 매우 낮음 네트워크 지연
실패 원인 코드/라이프사이클 네트워크/서버
사용 목적 내부 작업 분리 서버 통신
  • 메시지 라이프 사이클 연구 필요

핵심

  • 메시지는 스레드/컨텍스트 간 유일한 통신 수단
  • 함수 호출, 공유 메모리 X
  • 이벤트 기반 비동기 통신
  • 데이터 전달이지 “로직 실행”이 아님
  • 공유 메모리에 대한 연구 필요

메시지의 패턴 - 설계

메시지 설계란

  • 워커와 메인 스레드 사이의 프로토콜(API계약)을 정의하는 일
  • 어떤 타입의 메시지를, 어떤 데이터 구조로, 어떤 순서로 주고받을지 결정

메시지 타입

  • 구조 - 권장 포맷
  • type WorkerMessage<T = any> = { type: string; payload?입
  • 타입과 역할 → 위의 구조 안에 type 을 말함
    • 메시지 타입이 곧 “API 엔드포인트” 역할
    타입 방향 역할
    INIT Main → Worker 워커 초기 설정
    TICKS Main → Worker 원시 데이터 배치 전달
    SNAPSHOT Worker → Main 렌더용 결과 반환
    RESET Main → Worker 상태 초기화
    STATS Worker → Main 성능/상태 모니터링
    ERROR Worker → Main 에러 보고
    TERMINATE Main → Worker 작업 중단

상태 분리

단계 설명

INIT 설정은 한 번만
TICKS 데이터만 반복 전달
Worker 내부 상태 유지 (ring buffer 등)

코드 예시

  • Worker 코드
  • self.onmessage = (event) => { const { type, payload } = event.data; switch (type) { case 'INIT': { // 초기 설정 self.config = payload; break; } case 'TICKS': { // 대용량 데이터 처리 const result = processTicks(payload); self.postMessage({ type: 'SNAPSHOT', payload: result, }); break; } case 'RESET': { resetState(); break; } } };
  • 메인 스레드 코드 - Nextjs 클라이언트 컴포넌드
  • const worker = new Worker( new URL('./chart.worker.ts', import.meta.url) ); worker.postMessage({ type: 'INIT', payload: { timeframe: 1000, maxPoints: 2000, }, }); worker.postMessage({ type: 'TICKS', payload: ticks, }); worker.onmessage = (event) => { const { type, payload } = event.data; if (type === 'SNAPSHOT') { updateChart(payload); } };

ArrayBuffer를 쓰는 메세지 예제

  • 전달 메시지 (Transable)
  • worker.postMessage( { type: 'TICKS', payload: buffer, }, [buffer] // 소유권 이동 );
  • Worker 수신

+ Recent posts