[JavaScript] Web Workers

Narcoker·2023년 6월 17일
0

JavaScript

목록 보기
47/55

Web Workers

웹 애플리케이션에서 다중 스레드를 사용하여 백그라운드에서 스크립트를 실행할 수 있게 하는 API이다.

이는 자바스크립트가 싱글 스레드 기반이므로
주요 페이지 렌더링 및 사용자 상호작용을 차단하지 않고
복잡한 또는 시간이 오래 걸리는 작업을 수행할 수 있게 한다.

Web Worker에서는 DOM을 사용할 수 없으며
Window와 API 사용에도 제약이 있다.

new Worker()

전용 Worker를 생성하여 반환한다.
다수의 Worker를 만들어서 사용할 수 있다.

멀티스레딩이 가능하다는 것이된다.
참고로 Node.js 환경에서는 worker_threads 라는 별도의 모듈로 멀티스레딩을 구현할 수 있다.

파라미터 : source 파일 URL
이때 URL은 메인 코드와 동일한 출처여야한다.

// worker.js
self.onmessage = (event) => {
	const  data= event.data;
};

// main.js
const main = new Worker("worker.js"); // worker.js 파일의 코드를 자동으로 실행한다.

Worker.postMessage()

해당 스레드에서 Worker로 메세지를 보낸다.

파라미터: 전송할 변수, [전송할 변수](Transferable 오브젝트)

Transferable 오브젝트를 전송한다는 것은 소유권을 넘겨준다는 의미이다.

// transfer.js
self.onmessage = (event) => {
	const view = new DataView(event.data);
    view.setInt8(1,20);
    self.postMessage(event.data);
};

//main.js
const main = new Worker('transfer.js");
const buffer = new ArrayBuffer(3);
const view = new DataView(buffer);
view.setInt8(0,10);
main.postMessage(buffer, [buffer]);
try {
	view.setInt8(1,30);
} catch {
	console.log("사용할 수 없음);
};
main.onmessage = (event) => {
	const view = new DataView(event.data);
   	console.log(view.getInt8(0));
    console.log(view.getInt8(1));
};

/*
사용할 수 없음
10
20
*/

WorkerGlobalScope

웹 워커 내부에서 사용 가능한 범위(scope)를 나타내는 객체

웹 Worker Context에서는 이 WorkerGlobalScope 객체가 전역 객체로 작동한다.
즉, Worker의 글로벌 오브젝트이다.

Event 오브젝트를 상속 받는다.

self 키워드

WorkerGlobalScope를 가리킨다. 메인 스레드에서의 window 객체와 비슷한 역할을 한다.
WorkerGlobalScope의 메소드를 사용하려면 self를 작성하지 않아도 되지만
일반적으로 작성한다.

self.postMessage()

Worker에서 메인 스레드로 값을 얕은 복사하여 메시지를 보낸다.
오브젝트가 큰 경우에는 복사 시간이 오래 걸린다.

self.onmessage()

이벤트 핸들러를 사용하여 메인 스레드에서 보낸 매세지를 수신할 수 있다.

self.importScripts()

1개 이상에 자바스크립트 파일을 동기적으로 Worker오브젝트에 설정한다.

// add.js
const BASE = 100;
function add(param);{
	return BASE + param;
};
// global.js
importScripts("add.js");
onmessage = (event) => {
	const sum = add(event,data);
    postMessage(sum);
};    
// main.js
const main = new Worker("global.js");
main.postMessage(500);
main.onmessage = (event) => {
	console.log("계산 결과: ", event.data);
};

// 계산 결과: 600

SharedArrayBuffer

공유 메모리에 SharedsArrayBuffer를 생성하고
메인 스레드와 Worker에서 공유한다.
또한 ShardArrayBuffer는 ArrayBuffer 기능을 그대로 사용할 수 있다.

// worker.js
self.onmessage = (event) => {
	const obj = new Int16Array(event.data);
    obj[2] = 30;
    self.postMessage(event.data);
};

// main.js
const main = new Worker("worker.js");
const sab = new SharedArrayBuffer(10);
const obj = new Int16Array(sab);
obj.set([10]);
main.postMessage(sab);
obj[1] = 20;
main.onmessage = (event) => {
	obj.forEach((value => { console.log(value) });
};    

/*
10
20
0
0
0
*/

고려사항

Worker는 다수의 스레드 처리이다.

SharedArrayBuffer를 공유하기 때문에
사용 중일때는 lock 상태로 설정하고 사용이 끝나면 lock 상태를 푸는 등의
동기화 처리를 해줘야한다.

Atomics

SharedArrayBuffer 공유에 따른 동기화처리를 위한 오브젝트이다.

현재 명령어가 실행되는 동안 다른 스레드의 명령어를 실행되지 않도록 한다.
동기로 오퍼레이션을 실행한다.

Atomics 오브젝트는 생성자가 없다.
대신 Atomics.store() 형태로 작성한다.

Global 오브젝트가 스코프이다.

Atomics.store()

파라미터

typedArray 값을 저장할 공유 타이핑된 배열을 의미한다.
index 값이 저장될 배열의 위치를 나타낸다.
value 저장될 값이다.

const sab = new ShardArrayBuffer(10);
const obj = new Int16Array(sab);
console.log(Atomics.store(obj, 0, 100)); // 100
profile
열정, 끈기, 집념의 Frontend Developer

0개의 댓글