ArrayBuffer와 TypedArray — 바이너리 데이터 처리
이미지 처리, 오디오 조작, 네트워크 프로토콜, WebGL 같은 저수준 작업에서는 바이너리 데이터를 직접 다뤄야 합니다. ArrayBuffer와 TypedArray는 자바스크립트에서 바이너리를 효율적으로 처리하는 핵심 API입니다.
ArrayBuffer — 고정 크기 바이너리 버퍼
// 16바이트 버퍼 생성
const buffer = new ArrayBuffer(16);
console.log(buffer.byteLength); // 16
// ArrayBuffer를 직접 읽거나 쓸 수 없음!
// TypedArray나 DataView를 통해 접근해야 함
TypedArray — 버퍼에 타입 뷰 씌우기
const buffer = new ArrayBuffer(16);
// 같은 버퍼에 다른 뷰
const int32View = new Int32Array(buffer);
console.log(int32View.length); // 4 (16바이트 / 4바이트)
const uint8View = new Uint8Array(buffer);
console.log(uint8View.length); // 16 (16바이트 / 1바이트)
// 쓰기
int32View[0] = 42;
console.log(uint8View[0]); // 42 — 같은 메모리를 공유
// 직접 생성 (내부적으로 ArrayBuffer 자동 생성)
const arr = new Float64Array([1.1, 2.2, 3.3]);
console.log(arr.buffer.byteLength); // 24 (8바이트 * 3)
TypedArray 종류
| 타입 | 크기 | 범위 |
|---|---|---|
Int8Array | 1바이트 | -128 ~ 127 |
Uint8Array | 1바이트 | 0 ~ 255 |
Uint8ClampedArray | 1바이트 | 0 ~ 255 (클램핑) |
Int16Array | 2바이트 | -32768 ~ 32767 |
Uint16Array | 2바이트 | 0 ~ 65535 |
Int32Array | 4바이트 | -2^31 ~ 2^31-1 |
Uint32Array | 4바이트 | 0 ~ 2^32-1 |
Float32Array | 4바이트 | 단정밀도 부동소수점 |
Float64Array | 8바이트 | 배정밀도 부동소수점 |
BigInt64Array | 8바이트 | BigInt |
BigUint64Array | 8바이트 | BigInt (양수) |
DataView — 혼합 타입 접근
const buffer = new ArrayBuffer(12);
const view = new DataView(buffer);
// 다른 타입의 데이터를 하나의 버퍼에 저장
view.setUint32(0, 1234); // 오프셋 0: 32비트 정수
view.setFloat32(4, 3.14); // 오프셋 4: 32비트 실수
view.setUint16(8, 256); // 오프셋 8: 16비트 정수
view.setUint16(10, 512, true); // 리틀엔디안
console.log(view.getUint32(0)); // 1234
console.log(view.getFloat32(4)); // 3.140000104904175
실전 — 이미지 픽셀 조작
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const pixels = imageData.data; // Uint8ClampedArray
// 그레이스케일 변환
for (let i = 0; i < pixels.length; i += 4) {
const r = pixels[i];
const g = pixels[i + 1];
const b = pixels[i + 2];
const gray = (r + g + b) / 3;
pixels[i] = pixels[i + 1] = pixels[i + 2] = gray;
// pixels[i + 3]은 알파(투명도) — 유지
}
ctx.putImageData(imageData, 0, 0);
실전 — fetch로 바이너리 다운로드
async function downloadBinary(url) {
const response = await fetch(url);
const buffer = await response.arrayBuffer();
return new Uint8Array(buffer);
}
// WAV 파일 헤더 파싱 예시
async function parseWavHeader(url) {
const data = await downloadBinary(url);
const view = new DataView(data.buffer);
return {
chunkId: String.fromCharCode(...data.slice(0, 4)),
fileSize: view.getUint32(4, true),
format: String.fromCharCode(...data.slice(8, 12)),
sampleRate: view.getUint32(24, true),
bitsPerSample: view.getUint16(34, true),
};
}
TypedArray와 일반 Array 차이
const typed = new Int32Array([1, 2, 3]);
const normal = [1, 2, 3];
// 타입 강제
typed[0] = 3.14;
console.log(typed[0]); // 3 (정수로 잘림)
// 길이 고정
// typed.push(4); // TypeError — 크기 변경 불가
// 배열 메서드 일부 사용 가능
typed.map((x) => x * 2); // Int32Array [2, 4, 6]
typed.filter((x) => x > 1); // Int32Array [2, 3]
typed.find((x) => x === 2); // 2
// 성능: TypedArray가 대량 숫자 처리에 훨씬 빠름
변환
// TypedArray → 일반 Array
const typed = new Uint8Array([1, 2, 3]);
const arr = Array.from(typed);
const arr2 = [...typed];
// 일반 Array → TypedArray
const typed2 = new Float64Array([1.1, 2.2, 3.3]);
// TypedArray → ArrayBuffer
const buffer = typed.buffer;
// 문자열 → ArrayBuffer (TextEncoder)
const encoder = new TextEncoder();
const encoded = encoder.encode("안녕하세요");
console.log(encoded); // Uint8Array
// ArrayBuffer → 문자열 (TextDecoder)
const decoder = new TextDecoder("utf-8");
const decoded = decoder.decode(encoded);
console.log(decoded); // "안녕하세요"
**기억하기 **: ArrayBuffer는 바이너리 데이터의 컨테이너이고, TypedArray는 특정 숫자 타입으로 읽고 쓰는 "뷰"입니다. 이미지/오디오/네트워크 프로토콜 같은 저수준 작업에서 사용되고, Web Worker의 Transferable Objects와 함께 쓰면 대용량 데이터를 효율적으로 전달할 수 있습니다.
댓글 로딩 중...