Web Worker로 메인 스레드 부하 줄이기

Web Worker란 무엇인가

자바스크립트는 기본적으로 싱글 스레드에서 동작합니다. 즉 화면을 그리는 작업, 사용자 클릭을 처리하는 작업, 무거운 연산을 처리하는 작업이 모두 하나의 스레드(메인 스레드)에서 순서대로 실행됩니다. 만약 복잡한 연산이 오래 걸리면 그 시간 동안 화면이 멈추고 버튼도 눌리지 않는 현상이 발생합니다. Web Worker는 이런 문제를 해결하기 위해 브라우저가 제공하는 API로, 메인 스레드와는 별개의 백그라운드 스레드에서 자바스크립트 코드를 실행할 수 있게 해줍니다.

비유하자면 메인 스레드는 카페에서 주문도 받고 커피도 내리고 청소도 하는 혼자 일하는 직원과 같습니다. 손님이 몰리면 주문 받는 것도 늦어지죠. Web Worker는 이 직원 옆에 커피만 전담으로 내려주는 보조 직원을 하나 더 두는 것과 같습니다. 덕분에 원래 직원은 주문 응대에 집중할 수 있습니다.

동작 원리와 사용 예시

Worker는 메인 스레드와 메모리를 공유하지 않습니다. 대신 postMessage()로 데이터를 주고받으며 통신합니다. 이 구조 덕분에 동시에 같은 변수를 건드려서 생기는 충돌 문제가 원천적으로 차단됩니다.

사용법은 비교적 단순합니다. 먼저 별도의 자바스크립트 파일을 하나 만듭니다.

// worker.js
self.onmessage = function (e) {
const result = heavyCalculation(e.data)
self.postMessage(result)
}

메인 스크립트에서는 다음과 같이 Worker를 생성하고 메시지를 주고받습니다.

const worker = new Worker('worker.js')
worker.postMessage(inputData)
worker.onmessage = function (e) {
console.log('결과: ', e.data)
}

이 구조에서 heavyCalculation 같은 무거운 연산은 Worker 스레드 안에서 처리되므로, 메인 스레드는 그동안 자유롭게 화면을 그리고 클릭 이벤트를 처리할 수 있습니다. 단, Worker 내부에서는 DOM에 직접 접근할 수 없다는 제약이 있어 화면 조작은 반드시 메인 스레드로 결과를 전달한 뒤 처리해야 합니다.

실무에서 왜 사용하는가

실무에서 Web Worker는 다음과 같은 상황에서 유용하게 쓰입니다.

  • 대용량 이미지나 파일을 클라이언트에서 파싱하거나 압축할 때
  • 복잡한 데이터 정렬, 필터링, 통계 계산을 프론트엔드에서 처리해야 할 때
  • 실시간으로 들어오는 대량 데이터를 가공해 화면에 반영해야 할 때

이런 작업을 메인 스레드에서 그대로 실행하면 스크롤이 끊기거나 입력 반응이 느려지는 이른바 ‘버벅임’ 현상이 나타납니다. Web Worker를 활용하면 사용자 인터페이스는 계속 부드럽게 반응하면서, 무거운 계산은 뒤에서 조용히 처리할 수 있습니다. 다만 Worker 생성 자체에도 비용이 들고 메시지 통신에도 오버헤드가 있으므로, 아주 짧게 끝나는 연산까지 무분별하게 Worker로 옮기는 것은 오히려 성능에 도움이 되지 않을 수 있습니다. 무거운 연산이 실제로 UI를 막고 있는지 먼저 프로파일링으로 확인한 뒤 도입하는 것이 바람직합니다.

댓글 남기기