자바스크립트/프로그래밍

자바스크립트 이진 데이터(Binary Data) 다루기, ArrayBuffer와 Typed Array(형식화 배열)

improvise0828 2022. 3. 23. 01:55

자바스크립트를 사용하면서 개발자는 직접 이진 데이터(Binary Data)를 다뤄야 할 경우가 있습니다.
개발자가 이진 데이터를 쉽게 읽고 쓰게 하기 위해서 자바스크립트는 ArrayBuffer와 Typed Array(형식화 배열)이라는 기능을 제공합니다.


ArrayBuffer란?

ArrayBuffer는 바이트로 구성된 배열로, 다른 언어에서는 종종 "바이트 배열"이라고 부릅니다.
(ArrayBuffer는 한 칸당 1바이트의 값을 가지는 배열입니다.)
일반적인 배열과 다르게 ArrayBuffer에 담긴 정보를 직접 읽거나 쓰는 것은 불가능합니다.
대신 형식화 배열 또는 DataView 객체를 통해 ArrayBuffer를 읽고 쓸 수 있습니다.

 

1. 형식화 배열을 사용해 ArrayBuffer를 읽고 쓰기

const buffer = new ArrayBuffer(4); // 총 4 바이트의 공간을 예약
new DataView(buffer).setUint16(0, 65535); // 0번 1번 바이트에 16비트 최대값 65535 입력
new DataView(buffer).setUint16(2, 65536); // 2번 3번 바이트에 16비트 최대값의 +1 오버플로우값 65536 입력
const view = new Uint16Array(buffer); // 16비트(2바이트) 단위를 사용하는 형식화 배열 선언
console.log(view);
// 출력
// Uint16Array {0: 65535, 1: 0}

 

2. DataView 객체를 사용해 읽고 쓰기

const buffer = new ArrayBuffer(2); // 총 2 바이트 예약
const view = new DataView(buffer); // 데이터 뷰 생성
view.setUint8(0, 255); // 0번 인덱스에 255 입력 (1 바이트의 최대값)
view.setUint8(1, 256); // 0번 인덱스에 256 값 입력 (1 바이트에서 + 1 오버플로우 되는 값)
console.log(view.getUint8(0)); // 255 출력
console.log(view.getUint8(1)); // 0 출력

 

 

이제 위의 코드를 하나 하나 풀어가면서 이해합니다.

 

ArrayBuffer 생성하기

최초에 new ArrayBuffer(길이)를 선언해 ArrayBuffer 객체를 만듭니다.

길이의 단위는 1바이트이므로 ArrayBuffer(4)를 선언하면 4바이트 길이의 데이터 버퍼가 생성됩니다.

const buffer = new ArrayBuffer(1);
// 길이가 1인 바이트 배열 생성 (저장 가능한 데이터는 최대 1바이트)

const buffer = new ArrayBuffer(4);
// 길이가 4인 바이트 배열 생성 (저장 가능한 데이터는 최대 4바이트)

 

DataView 생성하기

생성한 ArrayBuffer는 DataView 객체를 통해 읽고 쓰는 작업을 합니다.

const view = new DataView(ArrayBuffer);
const view = new DataView(ArrayBuffer, <byteOffset>, <byteLength>)
// ArrayBuffer 읽기 쓰기를 할 읽어들일 바이트 배열 객체
// byteOffset(옵션) 읽어들일 바이트 배열의 시작 인덱스
// byteLength(옵션) 읽어들일 바이트 배열의 길이
// (DataView 객체는 ArrayBuffer 객체를 생성한 뒤에 연결해줍니다.)

 

DataView 객체를 통해 ArrayBuffer에 값 저장하기

DataView.setUint8() 메소드를 실행하면 ArrayBuffer에 8비트(1바이트) 단위로 데이터를 저장할 수 있습니다.

예를 들어 DataView.setUint8(0, 255)는 ArrayBuffer의 0번 인덱스의 8비트(1바이트)에

255(이진법으로 11111111)를 저장하겠다는 뜻입니다.

 

DataView.setUint8(byteOffset, value, <littleEndian>)
// byteOffset 어디서부터 값을 저장할 지 표기 (0번 인덱스부터 저장하려면 0을 입력)
// value 저장하고 싶은 값
// littleEndian(옵션) 빅엔디언(BigEndian) 또는 리틀엔디언(littleEndian) 지정
// 기본값은 false, 리틀엔디언(true), 빅엔디언(false)

 

읽고 쓰는 단위(데이터 타입)는 여러 메소드에 따라 달라집니다.

setUint8(8비트, 1바이트) setUint16(16비트, 2바이트) setUint32(32비트, 4바이트) 등이 있으며

각 데이터 타입들은 아래의 그림처럼 ArrayBuffer에 접근합니다.

 

new ArrayBuffer(16) 기준

 

 

DataView 객체를 통해 ArrayBuffer에 값 읽기

DataView.getUint8() 메소드를 실행하면 ArrayBuffer에 8비트(1바이트) 단위로 데이터를 읽어올 수 있습니다.

예를 들어 DataView.getUint8(0) ArrayBuffer의 0번 인덱스를 읽어서 출력한다는 뜻입니다.

DataView.getUint8(byteOffset, littleEndian)
// byteOffset 어디의 값을 표시할지 (처음부터 표시하려면 0을 입력)
// littleEndian(옵션) 빅엔디언(BigEndian) 또는 리틀엔디언(littleEndian) 지정
// 기본값은 false, 리틀엔디언(true), 빅엔디언(false)

 

Typed Array를 사용해 ArrayBuffer를 읽을 수도 있습니다.

Typed Array(형식화 배열) 또한 DataView 객체의 일종으로 배열, 유사배열, Array Buffer 등의 데이터를 인자로 받아 생성합니다.

const buffer = new ArrayBuffer(2); // 총 2 바이트 예약
new DataView(buffer).setUint16(0, 1, true); // 제일 마지막 비트에 1 입력
const data = new Uint16Array(buffer);
console.log(data);
// 출력
// Uint16Array {0: 1}

 

다음의 문서를 참고해 작성했습니다.

1. ArrayBuffer 레퍼런스
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer

2. Typed Array(형식화 배열) 레퍼런스
https://developer.mozilla.org/ko/docs/Web/JavaScript/Typed_arrays

3. DataView(데이터 뷰) 레퍼런스
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/DataView