Conceptly
← 전체 목록
👷

Web Worker

클라이언트메인 스레드와 분리된 곳에서 무거운 JavaScript 작업을 실행하는 브라우저 워커

Web Worker는 웹 페이지의 메인 스레드와 분리된 별도 스레드 비슷한 실행 컨텍스트에서 JavaScript를 돌릴 수 있게 해 주는 브라우저 기능입니다. DOM에는 직접 접근할 수 없지만, 무거운 계산과 파싱을 메인 스레드 밖으로 옮겨 화면 렌더링과 사용자 입력이 계속 부드럽게 반응하도록 도와줍니다.

아키텍처 다이어그램

🔍 구조 다이어그램

점선 애니메이션은 데이터 또는 요청의 흐름 방향을 나타냅니다

왜 필요한가요?

브라우저의 메인 스레드는 화면 그리기, 클릭 처리, 스크롤, JavaScript 실행을 모두 함께 맡습니다. 여기에 큰 JSON 파싱이나 복잡한 계산, 이미지 처리 같은 작업이 들어오면 사용자가 버튼을 눌러도 반응이 늦고 스크롤이 끊깁니다. 흔히 말하는 'UI가 멈췄다'는 현상입니다. 이 문제는 JavaScript가 느려서가 아니라, 중요한 일들이 한 줄로 서서 차례를 기다리기 때문입니다. 계산 자체는 필요하지만, 그 계산이 화면 그리기와 같은 줄에 서 있지 않게 분리할 실행 모델이 필요합니다.

왜 이런 방식이 등장했나요?

초기의 웹 페이지는 문서와 약간의 상호작용만 다뤘기 때문에 메인 스레드 하나로도 충분했습니다. 하지만 브라우저 안에서 데이터 시각화, 오디오 편집, CAD, 대규모 테이블, ML 추론 같은 무거운 작업까지 처리하기 시작하면서, 메인 스레드만으로는 사용 경험을 유지하기 어려워졌습니다. 브라우저는 네이티브 앱처럼 스레드를 자유롭게 다루게 하지는 않지만, 최소한 계산을 분리할 수 있는 안전한 모델로 Web Worker를 제공합니다. 화면 접근은 막되, 별도 컨텍스트에서 코드를 실행하고 메시지로 협력하게 만든 것입니다.

안에서 어떻게 동작하나요?

메인 스레드는 `new Worker()`로 별도 스크립트를 실행시켜 Worker를 만듭니다. Worker 안에는 자신만의 전역 컨텍스트와 이벤트 루프가 있고, 그 안에서 무거운 계산이나 파싱을 수행합니다. 메인 스레드와 Worker는 공유 메모리를 기본으로 사용하지 않습니다. 대신 `postMessage`로 데이터를 주고받고, 브라우저는 그 데이터를 structured clone 방식으로 복사하거나 ArrayBuffer 같은 transferable 객체는 소유권을 넘깁니다. 그래서 Worker를 쓸 때는 함수 호출보다 메시지 계약을 설계하는 감각이 중요합니다. Worker는 DOM을 직접 읽거나 바꿀 수 없습니다. 계산 결과를 메인 스레드로 돌려보내면, 화면 반영은 메인 스레드가 맡습니다. 이 제약 덕분에 계산 분리는 가능하지만 UI 일관성은 브라우저가 유지할 수 있습니다.

무엇과 헷갈리나요?

Web Worker와 Service Worker는 둘 다 메인 스레드 밖에서 실행되지만, 현재 열린 페이지와의 관계가 다릅니다. Web Worker는 페이지가 살아 있는 동안 그 페이지를 위해 계산을 대신 수행하는 도구이고, Service Worker는 페이지와 네트워크 사이에서 캐시와 백그라운드 이벤트를 처리하는 브라우저 측 워커입니다. 또 Web Worker는 DOM을 만질 수 없다는 점을 명확히 기억해야 합니다. 화면이 느리다고 해서 DOM 조작 자체를 Worker로 옮길 수는 없고, 계산이나 파싱처럼 CPU를 오래 잡는 부분만 분리할 수 있습니다. 무엇이 메인 스레드에 남고 무엇이 밖으로 나갈지 경계가 중요합니다.

언제 쓰나요?

Web Worker는 브라우저 안에서 꽤 무거운 계산을 해야 하는 제품에서 효과가 즉각적입니다. 로그 검색, 대용량 테이블 필터링, 이미지 변환, 실시간 메시지 파싱처럼 사용자가 기다리는 동안 메인 스레드를 막아서는 안 되는 작업이 대표적입니다. 실무에서는 Worker를 너무 잘게 쪼개는 것보다, 메인 스레드를 실제로 막는 작업을 먼저 분리하는 편이 낫습니다. 메시지를 너무 자주 주고받으면 통신 비용이 커져 기대한 만큼 이득이 나지 않을 수 있기 때문입니다. 또 Worker가 있다고 해서 메모리와 데이터 복사 비용이 사라지는 것은 아닙니다. 큰 객체를 매번 복사하면 오히려 부담이 커질 수 있으므로, transferable 객체를 쓰거나 메시지 크기를 줄이는 설계가 중요합니다. 핵심은 '아무 작업이나 옮기는 것'이 아니라, 사용자 체감을 해치는 병목을 메인 스레드 밖으로 빼는 것입니다.

대용량 데이터 가공이미지·파일 처리WASM 연산실시간 스트림 처리