
독립적인 데이터 조각
고정된 크기의 연속적인 메모리 공간을 나타내는 객체
데이터를 읽고 쓰기 위해 데이터 뷰가 필요
동작 방식: 메인 스레드와 워커 스레드는 완전한 동일한 내용을 가진, 하지만 서로 다른 메모리 공간에 존재하는 별개의 ArrayBuffer를 갖게 된다
장점: 각 스레드가 독립적인 데이터 복사본을 가지므로 여러 스레드가 동시에 데이터에 접근할 때 발생하는 복잡한 동시성 문제(레이스 컨디션)을 걱정할 필요가 없음
단점: 데이터의 크기가 클수록 복사하는 데 상당한 시간과 자원이 소모됨 -> 성능 저하
new ArrayBuffer() 생성자를 사용하여 고정된 크기의 원시 바이너리 데이터 버퍼를 바이트 단위로 생성// 16바이트 크기의 버퍼 생성
const buffer = new ArrayBuffer(16);
View: ArrayBuffer 자체는 원시적인 바이트 덩어리이므로, Int32Array나 Uint8Array같은 TypedArray를 통해 데이터를 읽고 쓸 수 있는 뷰를 만들어야 한다.
TypedArray: Uint8Array, Int32Array 등 특정 숫자 형식으로 버퍼를 다룰 때 사용한다. 버퍼를 일정한 크기(예: 8비트, 32비트)로 나누어 배열처럼 다룰 수 있게 해준다.
DataView: 버퍼 내 다른 형식의 데이터를 다룰 때 유연성을 제공하며, 특정 오프셋에서 원하는 형식으로 데이터를 읽고 쓸 수 있다.
생성된 ArrayBuffer 객체는 worker.postMessage() 를 통해 웹 워커로 전달할 수 있다.
두 가지 방식이 가능하다.
데이터 복사 (기본): postMessage 호출 시 데이터 전체가 복사되어 워커에 새로운 버퍼가 생성된다.
이 방식은 데이터 크기가 클 경우 성능 저하를 유발할 수 있다.
소유권 이전 (Transferable): ArrayBuffer는 소유권 이전이 가능한 객체(Transferable Object)다.
postMessage 의 두 번째 인자로 버퍼를 전달하면, 데이터 복사 없이 소유권이 워커로 즉시 이전된다. 이 경우, 원래 스레드(예: 메인 스레드)에서는 해당 버퍼에 더 이상 접근할 수 없게 된다. 이 방식이 훨씬 효율적이다.
// buffer의 소유권을 워커로 이전
worker.postMessage(buffer, [buffer]);
워커는 전달받은 버퍼를 자체 뷰를 통해 수정한다.
수정된 데이터를 다시 메인 스레드로 보내야 할 경우, 워커는 다시 postMessage를 통해 버퍼의 소유권을 메인 스레드로 이전해야 한다.
이러한 방식 때문에 여러 스레드가 동시에 데이터를 수정하는 경쟁 상태(Race Condition)가 발생하지 않으므로, Atomics 객체를 사용한 동기화가 필요 없다.
공유되는 메모리 공간
ArrayBuffer와 똑같이 고정된 크기의 연속적인 메모리 공간을 나타냄
핵심적인 차이는 데이터를 다른 스레드에 전달할 때에 있다
동작 방식: 메인 스레드와 워커 스레드가 완전히 동일한 메모리 주소를 바라보게 됨
SharedArrayBuffer의 데이터를 변경하면, 다른 스레드에서도 즉시 그 변경 사항을 확인할 수 있다장점: 데이터 복사 과정이 없으므로 매우 빠르고 효율 적이다.
단점: 여러 스레드가 동일한 메모리에 동시에 접근 가능하므로, 레이스 컨디션과 같은 문제가 발생할 수 있다.
new SharedArrayBuffer()를 사용해 공유할 메모리 공간(버퍼)을 바이트 단위로 생성Int32Array나 Uint8Array같은 TypedArray를 통해 데이터를 읽고 쓸 수 있는 뷰를 만들어야 한다.SharedArrayBuffer 객체를 worker.postMessage()를 통해 웹 워커로 전달한다.Atomics 객체를 통해 동기화로 해결한다.ArrayBuffer나 SharedArrayBuffer는 그 자체로는 의미가 없는 원시 이진 데이터다.
단순히 메모리 공간에 연속된 바이트들을 확보해 놓은 것에 불과하다.
이 안의 데이터를 직접 읽거나 쓸 수는 없다.
이런 데이터를 해석하고 조작할 수 있는 통로 역할을 하는 객체가 데이터 뷰이다.
어떤 자료형(e.g. 8비트 정수, 32비트 부동소수점 수)으로, 어떤 순서로 데이터를 읽고 쓸지 결정하는 역할을 한다.
JS에서 사용하는 데이터 뷰는 두 가지 종류가 있다.
ArrayBuffer나 SharedArrayBuffer 의 전체 데이터를 하나의 통일된 숫자 형식으로 해석하는 뷰이다.
Int8Array, Uint32Array, Float64Array 등이 모두 TypedArray의 한 종류이다.
// 8바이트 크기의 메모리 공간(버퍼)을 생성
const buffer = new ArrayBuffer(8);
// Int32Array 뷰로 버퍼를 해석 (4바이트 정수 2개)
const view_int32 = new Int32Array(buffer);
view_int32[0] = 987654321;
console.log(view_int32[0]); // 987654321
메인 스레드와 완전히 분리된 백그라운드 스레드에서 스크립트를 실행할 수 있게 해주는 기술
웹 워커가 필요한 이유
특징