Web Worker

Web Worker란 무엇인가?


Web Worker란, script 실행을 main thread(UI thread)가 아니라 background thread에서 실행할 수 있도록 해주는 API이다.

*thread란, 어떤 프로그램 내에서 실행되는 흐름의 단위로, 보통 한 프로그램이 하나의 thread를 가지고 있다. 하나의 thread를 갖는다는 의미는, 어떤 이벤트(행위)가 발생했을 때, 그 하나의 이벤트를 처리할 때까지 다른 일은 못하게 된다는 뜻이다. 즉, 한번에 하나씩 처리한다는 뜻이다.

둘 이상의 thread를 동시에 실행하는 방식을 multi thread라고 한다. 웹 브라우저상의 javascript는 싱글 thread이기 때문에, 한번에 하나의 일 밖에 처리를 못한다. 그래서, 웹페이지에서 script가 실행되면, 해당 웹 페이지는 실행 중인 script가 종료될 때까지 응답 불가 상태, 즉 다른 일을 처리할 수가 없다.

이때, Web Worker를 사용하면, 시간이 오래 걸리는 javascript 작업 등을 background에서 처리하게 하여, 사용자의 UI를 방해하지 않고, 작업을 수행할 수 있다. 즉, script의 multi thread가 가능하게 된다.


Web Worker를 왜 사용하는가?


Web Worker를 사용하는 이유는, script 작업이 복잡하여 시간이 오래 걸리는 경우에도, 사용자의 다른 UI 작업에 방해를 주지 않기 위한 multi thread가 가능하기 때문이다.

Web Worker의 활용

  • 사용자의 UI 작업(UI thread)에 방해 없이 계속 수행해야하는 작업이 있을 경우
  • background에서 오랜시간 동안 작업해야 하는 경우
  • 원격에 있는 리소스에 대한 액세스 작업(localstorage를 액세스 하는 경우)이 있을 경우
  • 복잡한 수학적 계산 작업이 있을 경우

Web Worker를 사용하기 예전 상황

  • 스크립트가 수행을 하는데 오랜 시간이 걸릴 때, 브라우저는 무반응 스크립트에 대한 경고를 보여줌
  • webworker를 이용한 이후에는 이 문제 해결


Web Worker를 어떻게 사용하는가?


  • How Web Worker works
  • 기본적인 사용방법


How Web Worker Works


How Web Worker Works
출처: How Web Worker Works

Main script가 실행되는 HTML 파일(웹페이지)과 background script가 실행되는 Worker가 있다. HTML 파일(웹페이지)과 Worker간의 데이터를 서로 주고 받으면서, script가 실행되는 방식이다.

이때, 데이터를 송신할 때는 postMessage 메서드를 사용하고, 데이터를 수신할 때는 onmessage 이벤트 핸들러를 사용한다. HTML 파일(웹페이지)에서 데이터를 송신하거나 수신할 수 있고, Worker에서도 데이터를 송신하거나 수신할 수 있다.

postMessage는 다수의 window 창간의 정보교환을 목적으로 사용한다. workers는 DOM에 대한 접근 권한이 없어서 직접 웹페이지를 조작이 불가능하다.


Web Worker의 기본적인 사용방법


코드상으로 Web Worker를 사용하기 위해서는 다음과 같이 해야한다.

  • Worker 실행 파일(worker.js) 작성
  • Worker를 호출할 HTML 파일(웹페이지)에서 Worker를 호출
  • Worker 종료


Worker 실행 파일(worker.js) 작성


Worker가 실행할 script, 즉 javascript(worker.js) 파일을 만들고 작성한다. 이때, on message 이벤트 핸들러와 postMessage 메서드를 같이 작성한다. 왜냐하면, HTML 페이지로부터 전달 받을 데이터를 onmessage 이벤트 핸들러로 수신받아 처리한 후, postMessage 메서드로 다시 HTML 페이지에 전달해줘야 하기 때문이다.

1
2
3
4
5
6
7
8
9
10
11
12
// worker.js

//웹페이지로부터 메세지를 수신하여 시간이 오래 걸리는 작업 등을 처리
onmessage = function(e){
var receiveData = e.data;

//워커를 호출한 곳(웹페이지)으로 결과 메시지를 전송
if(receiveData) {
var sendData = "I'm working for you"
postMessage(sendData)
}
}


Worker를 호출할 HTML 파일(웹페이지)에서 Worker를 호출


New 연산자와 Worker 생성자 함수를 이용해 worker 인스턴스를 생성한다. 생성한 worker 인스턴스를 사용해서, Worker(worker.js)에 보낼 데이터를 postMessage 메서드를 이용해 작성하고, 후에, Worker(worker.js)에서 처리된 후 받을 데이터를 on message 이벤트 핸들러를 이용해 작성한다.

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
32
33
34
35
36
37
38
39
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var worker;
function callWorker(){
if(!!window.Worker){ //브라우저가 웹 워커를 지원하는지 확인

if(worker) worker.terminate(); //워커가 이미 존재하면 종료시킴
worker = new Worker("worker.js"); //새로운 워커(객체)를 생성

//워커로부터 전달되는 메시지를 받음
worker.onmessage = function(e){
alert(e.data);
};

//워커에게 메시지를 전달
worker.postMessage("What does Worker do?");
}
else{
alert("The current browser does not support web worker api")
}
}

function stopWorker(){
if(worker){
worker.terminate();
alert("web worker has terminated");
}
}
</script>
</head>
<body>
<button onclick="callWorker()">Call web worker</button>
<button onclick="stopWorker()">Stop web worker</button>
<br>
<input type="text">
</body>
</html>


Worker 종료


Worker 인스턴스는 생성되고 종료될 때까지 계속해서 데이터를 받을 준비를 한다. 그래서, 브라우저나 컴퓨터의 자원을 돌려주기 위해 terminate() 메서드를 사용하여, worker를 반드시 종료해야 한다.

1
worker.terminate();