[Javascript] 11강 형식화 배열
형식화 배열(typed array)은 배열같은 원시(row) 이진 데이터에 엑세스하기 위한 매커니즘을 제공합니다. Array 객체는 동적으로 늘어나다 줄어들고 어떤 Javascript 값이든 가질 수 있습니다. Javascript 엔진은 이렇한 배열이 빨라지도록 최적화를 수행합니다.
그러나, audio 및 video 태그 조작과 관련된 기능 추가, WebSocket은 원시 데이터에 엑세스 등 웹 어플리케이션이 점점 더 강력해짐에 따라, 빠르고 쉽게 형식화 배열의 원시 이진 데이터를 조작할 수 있게 하는 것이 코드에 도움이 될때가 있음을 분명해졌습니다.
그러나, 형식화 배열은 보통 배열과 혼동되지는 않고, 형식화 배열의 Array.isArray() 호출은 false를 반환하기에, 보통 배열에 이용할 수 있는 모든 메서드가 형식화 배열에 의해 지원되지는 않습니다(push 나 pop)
1. 버퍼 및 뷰: 형식화 배열 구조
최대 유연성 및 효율을 달성하기 위해, 형식화 배열에서는 구현을 버퍼 및 뷰로 나뉩니다. 버퍼(ArrayBuffer 객체에 의해 구현)는 데이터 부분(chunk, 덩어리)을 나타내는 객체로 이야기할 형식이 없고, 그 콘텐츠에 엑세스하기 위한 메커니즘을
제공하지 않습니다. 버퍼에 포함된 메모리에 엑세스하기 위해, 뷰를 사용할 필요가 있습니다. 뷰는 문맥(context)을 제공해 데이터를 실제 형식화 배열로 바꿉니다.
ArrayBuffer
ArrayBuffer는 일반 고정 길이 이진 데이터 버퍼를 나타내는 데 사용되는 데이터형으로, ArrayBuffer 콘텐츠를 직접 조작은 불가능합니다. 대신 형식화 배열 뷰 또는 특정 형식으로 버퍼를 나타내는 DataView를 만들어 버퍼의 콘텐츠를 읽고 쓰기 위해 사용합니다.
형식화 배열 뷰
형식화 배열 뷰는 자체 설명형 이름이 있으며, Int8, Uint32, Float64 등과 같은 모든 일반 숫자 형을 위한 뷰를 제공합니다. 특별한 형식화 배열 뷰는 Uint8ClampedArray가 있으며 값은 0에서 255 사이로 단속(제한)합니다.
DataView
DataView는 버퍼에 임의 데이터를 읽고 쓰기 위해 getter/setter API를 제공하는 저레벨 인터페이스로, 서로 다른 유형의 데이터를 처리하는 경우 유용하게 쓰입니다. 형식화 배열 뷰는 플랫폼의 본디(native) 바이트 순서(byte-order, endiannes 참조)에 속합니다. DataView로 바이트 순서를 제어할 수 있습니다. 기본으로 big-endian이고 getter/setter 메서드로 little-endian으로 설정될 수 있습니다.
형식화 배열을 사용하는 웹 API
- FileReader.prototype.readAsArrayBuffer()
- XHMLHttpRequest.prototype.send()
- XMLHttpRequest 인스턴스의 send() 메서드는 형식화 배열 및 인수로 ArrayBuffer 객체를 지원
- ImageData.data
- 0에서 255까지 정수값으로 RGBA 순 데이터를 포함하는 1차원 배열을 나타내는 Uint8ClampedArray
버퍼와 뷰 사용하기
우선 16바이트 고정 길이로 버퍼를 만들어야 합니다.
var buffer = new ArrayBuffer(16); // 16 byte
이 시점에서, 바이트가 모두 0으로 미리 초기화된 메모리 덩어리가 있습니다. 그렇지만 이거를 가지고 할 수 있는 게 그렇게 많지 않고, 실제 16바이트 길이인지만 확인할 용도밖에 안됩니다.
var buffer = new ArrayBuffer(16); // 16 byte
if (buffer.byteLength === 16) {
console.log("Buffer is 16 Bytes"); // 16Byte true
} else {
console.log("noop, buffer Wrong!"); // 16Byte false
}
이 버퍼로 작업하기 전, 뷰를 만들어야 합니다. 32비트 부호있는 정수 배열로 버퍼의 데이터를 다루는 뷰를 만듭니다.
var int32View = new Int32Array(buffer);
for (var i = 0; i < int32View.length; i++) {
console.log((int32View[i] = i * 2)); // 0 2 4 6
}
이는 배열의 4항목을 값 0,2,4 및 6으로 채웁니다 ( 4항목이 각각 4바이트에 총 16바이트가 됨)
같은 데이터에 여러 뷰
같은 데이터에 여러 뷰를 만들 경우 다음과 같은 코드를 작성할 수 있습니다.
var int16View = new Int16Array(buffer); // 0 0 2 0 4 0 6 0
for (var i = 0; i < int16View.length; i++) {
console.log("Entry" + i + ":" + int16View[i]);
}
기존 32비트 뷰와 같은 버퍼를 공유하느 16비트 정수 뷰를 만들고 16비트 정수로 버퍼 내 모든 값을 출력합니다. 이제 출력 0,0,2,0,4,0,6,0을 얻습니다.
int16View[0] = 32;
console.log("Entry 0 is the 32-bit array is now" + int32View[0]);
이로부터 출력은 "Entry 0 in the 32-bit array is now32"입니다. 즉, 두 배열은 확실히 그저 같은 데이터 버퍼 상 뷰이며 버퍼를 서로 다른 형식으로 다루는 모든 뷰 유형으로 작업할 수 있습니다.
복잡한 데이터 구조(체)와 작업하기
단일 버퍼를 서로 다른 형인 여러 뷰(버퍼 내 서로 다른 오프셋에서 시작)와 결합시켜, 여러 데이터 형을 포함하는 데이터 객체와 상호 작용할 수 있습니다. 예를 들어, 이는 WebGL, 데이터 파일 또는 js-ctypes를 사용하는 동안 사용해야 하는 C 구조체에서 복잡한 데이터 구조와 상호 작용하게 합니다.
struc someStruct {
unsigned long id;
char username[16];
float amountDue;
};
일반적인 C구조체를 생각해보면 이 같은 형식으로 데이터를 포함하는 버퍼 자바스크립트에도 엑세스할 수 있습니다.
var buffer = new ArrayBuffer(24);
// 버퍼 내 데이터 읽음
var idView = new Uint32Array(buffer, 0, 1);
var usernameView = new Uint8Array(buffer, 4, 16);
var amountDueView = new Float32Array(buffer, 20, 1);
보통 배열로 전환
형식화 배열을 처리한 뒤, Array 프로토타입의 도움을 받기 위해 보통 배열로 다시 변환하는 게 유용합니다. Array.from 또는 Array.from이 지원되지 않는 경우 다음 코드를 사용해 수행할 수 있습니다.
var typedArray = new Uint8Array([1, 2, 3, 4]);
normalArray = Array.prototype.slice.call(typedArray);
normalArray.length === 4;
normalArray.constructor === Array;
for (let i = 0; i < 4; i++) {
console.log(normalArray[i]); // 1 2 3 4
}
참고 자료
JavaScript 형식화 배열 - JavaScript | MDN
JavaScript 형식화 배열(typed array)은 배열같은 객체이고 원시(raw) 이진 데이터에 액세스하기 위한 메커니즘을 제공합니다. 이미 아시다시피, Array 객체는 동적으로 늘었다 줄고 어떤 JavaScript 값이든
developer.mozilla.org
GitHub - javascript-only/javascript-bloging
Contribute to javascript-only/javascript-bloging development by creating an account on GitHub.
github.com