JavaScript의 `DataView`

JavaScript의 `DataView`

이 문서는 JavaScript의 DataView를 설명합니다.

DataView의 기본 사용법과 구체적인 사용 사례에 대해 자세히 설명하겠습니다.

YouTube Video

JavaScript의 DataView

JavaScript의 DataView는 버퍼(ArrayBuffer)에 저장된 데이터를 다양한 형식으로 조작할 수 있는 편리한 API입니다. 이를 통해 이진 데이터를 유연하고 효율적으로 읽고 쓸 수 있으며, 네트워크 통신, 파일 처리 및 WebAssembly와의 인터페이스에서 중요한 역할을 합니다.

DataView란 무엇인가요?

DataViewArrayBuffer 객체 위에 보기 레이어(view layer)를 제공하여 정수, 부동소수점, 문자 등 다양한 데이터 타입을 임의의 바이트 오프셋에서 읽고 쓸 수 있게 합니다. DataViewTypedArray와 유사하지만, 엔디언(바이트 순서)을 지정하고 바이트 단위의 세부적인 작업을 수행할 수 있다는 점에서 차별화됩니다.

DataView의 기본 구문

1let buffer = new ArrayBuffer(16);  // Create a 16-byte ArrayBuffer
2let view = new DataView(buffer);    // Manipulate the buffer with a DataView

DataViewArrayBuffer를 인수로 받는 생성자를 가집니다. 이 예제에서는 16바이트 버퍼를 생성하고, DataView를 사용하여 해당 버퍼에 접근합니다. DataView를 사용하면, 버퍼에 저장된 데이터를 읽거나 쓸 때 바이트 크기와 엔디언(big-endian 혹은 little-endian)을 지정할 수 있습니다.

DataView의 기본 메서드

DataView는 다양한 데이터 타입의 값을 읽고 쓰는 메서드를 제공합니다. 이들은 주로 데이터를 읽는 get 메서드와 쓰는 set 메서드로 나뉩니다.

주요 메서드는 아래와 같습니다.

값을 읽는 메서드

  • getInt8(byteOffset): 지정된 오프셋에서 1바이트 부호 있는 정수를 읽습니다.
  • getUint8(byteOffset): 지정된 오프셋에서 1바이트 부호 없는 정수를 읽습니다.
  • getInt16(byteOffset, littleEndian): 2바이트 부호 있는 정수를 읽습니다.
  • getUint16(byteOffset, littleEndian): 2바이트 부호 없는 정수를 읽습니다.
  • getInt32(byteOffset, littleEndian): 4바이트 부호 있는 정수를 읽습니다.
  • getUint32(byteOffset, littleEndian): 4바이트 부호 없는 정수를 읽습니다.
  • getFloat32(byteOffset, littleEndian): 4바이트 IEEE 754 부동소수점 숫자를 읽습니다.
  • getFloat64(byteOffset, littleEndian): 8바이트 IEEE 754 부동소수점 숫자를 읽습니다.

값을 쓰기 위한 메서드들

  • setInt8(byteOffset, value): 1바이트 부호 있는 정수를 씁니다.
  • setUint8(byteOffset, value): 1바이트 부호 없는 정수를 씁니다.
  • setInt16(byteOffset, value, littleEndian): 2바이트 부호 있는 정수를 씁니다.
  • setUint16(byteOffset, value, littleEndian): 2바이트 부호 없는 정수를 씁니다.
  • setInt32(byteOffset, value, littleEndian): 4바이트 부호 있는 정수를 씁니다.
  • setUint32(byteOffset, value, littleEndian): 4바이트 부호 없는 정수를 씁니다.
  • setFloat32(byteOffset, value, littleEndian): 4바이트 IEEE 754 부동소수점 숫자를 씁니다.
  • setFloat64(byteOffset, value, littleEndian): 8바이트 IEEE 754 부동소수점 숫자를 씁니다.

이 메서드들을 사용하여 ArrayBuffer에 저장된 데이터를 유연하게 읽고 쓸 수 있습니다.

DataView 사용 예시

DataView를 사용하여 이진 데이터를 조작하는 예제를 살펴봅시다.

예제 1: 16비트 정수 쓰기와 읽기

1let buffer = new ArrayBuffer(4);  // Create a 4-byte buffer
2let view = new DataView(buffer);
3
4// Write a 2-byte integer value in little-endian format
5view.setInt16(0, 32767, true);  // byteOffset: 0, value: 32767, littleEndian: true
6
7// Read the data in little-endian format
8let value = view.getInt16(0, true);
9console.log(value);  // Output: 32767
  • 이 예제에서는 setInt16 메서드를 사용해 LITTLE_ENDIAN 형식으로 16비트 부호 있는 정수를 쓰고, getInt16 메서드로 그 값을 읽습니다.

예제 2: 부동소수점 숫자 쓰기와 읽기

1let buffer = new ArrayBuffer(8);  // Create an 8-byte buffer
2let view = new DataView(buffer);
3
4// Write an 8-byte floating-point number
5view.setFloat64(0, 3.14159, false);  // byteOffset: 0, value: 3.14159, bigEndian: false
6
7// Read the data in big-endian format
8let pi = view.getFloat64(0, false);
9console.log(pi);  // Output: 3.14159
  • 이 예제에서는 setFloat64 메서드를 사용해 BIG_ENDIAN 형식으로 64비트 부동소수점 숫자를 쓰고, getFloat64로 그 값을 읽습니다.

엔디언에 대하여

DataView를 사용하여 빅엔디안과 리틀엔디안 형식 모두에서 값을 읽고 쓰는 예제를 살펴봅시다.

 1// Example: Handling Endianness with DataView in TypeScript
 2// Create an ArrayBuffer of 4 bytes
 3const buffer = new ArrayBuffer(4);
 4const view = new DataView(buffer);
 5
 6// Store the same number (0x12345678) in both endian formats
 7// By default, DataView uses big-endian
 8view.setUint32(0, 0x12345678); // Big-endian
 9console.log("Big-endian (default):");
10console.log(buffer);
11
12// Overwrite the buffer with little-endian
13view.setUint32(0, 0x12345678, true); // Little-endian
14console.log("Little-endian:");
15console.log(buffer);
16
17// Read values back in both endian modes
18const bigEndianValue = view.getUint32(0); // Big-endian read
19const littleEndianValue = view.getUint32(0, true); // Little-endian read
20
21console.log("Read as Big-endian:", bigEndianValue.toString(16));
22console.log("Read as Little-endian:", littleEndianValue.toString(16));

DataView 메서드에서 데이터는 기본적으로 BIG_ENDIAN 형식(가장 중요한 바이트부터 가장 덜 중요한 바이트 순서)으로 저장되지만, LITTLE_ENDIAN이 선택적으로 지정 가능합니다. LITTLE_ENDIAN은 바이트 순서를 반대로 뒤집습니다 (가장 덜 중요한 바이트부터 가장 중요한 바이트로). 서로 다른 시스템과 네트워크 프로토콜이 서로 다른 엔디안 방식을 사용하기 때문에 데이터 엔디안 방식을 올바르게 처리하는 것이 중요합니다.

TypedArray와의 차이점

DataViewTypedArray의 차이점을 살펴봅시다.

 1// Example: TypedArray vs DataView
 2
 3// Create a 8-byte buffer
 4const buffer = new ArrayBuffer(8);
 5
 6// --- Using TypedArray (Int32Array) ---
 7const int32View = new Int32Array(buffer);
 8int32View[0] = 42;
 9int32View[1] = 100;
10
11console.log("TypedArray (Int32Array):");
12console.log(int32View); // Int32Array [42, 100]
13
14// --- Using DataView ---
15const dataView = new DataView(buffer);
16
17// Write different types of data at arbitrary byte offsets
18dataView.setInt8(0, 65);         // 1 byte
19dataView.setUint16(1, 500, true); // 2 bytes, little-endian
20dataView.setFloat32(3, 3.14, true); // 4 bytes, little-endian
21
22console.log("\nDataView:");
23console.log("Int8 at 0:", dataView.getInt8(0));      // 65
24console.log("Uint16 at 1:", dataView.getUint16(1, true)); // 500
25console.log("Float32 at 3:", dataView.getFloat32(3, true)); // 3.14
26
27/*
28Output:
29TypedArray (Int32Array):
30Int32Array [42, 100]
31
32DataView:
33Int8 at 0: 65
34Uint16 at 1: 500
35Float32 at 3: 3.140000104904175
36*/

TypedArrayArrayBuffer를 기반으로 버퍼 연산을 제공하지만, TypedArray는 각 데이터 타입의 고정된 길이와 형식을 가진 연속 데이터 조작에 적합합니다. 반면, DataView는 다양한 데이터 타입을 유연하게 다룰 수 있으며 엔디언스를 제어하는 것도 가능합니다. 따라서 DataView는 복잡한 바이너리 데이터를 구문 분석하고 구성하는 데 적합합니다.

요약

DataView는 JavaScript에서 바이너리 데이터를 처리하기 위한 강력한 API입니다. 정수, 부동 소수점 숫자 및 엔디언스 차이를 고려하면서 데이터 읽기 및 쓰기를 위해 ArrayBuffer에 직접 접근할 수 있습니다. 네트워크 통신 및 파일 형식 구문 분석과 같은 상황에서 유용하며, 바이트 단위 제어가 필요한 경우 필수적입니다. TypedArray와 함께 사용하면 더 효율적으로 이진 데이터를 조작할 수 있습니다.

위의 기사를 보면서 Visual Studio Code를 사용해 우리 유튜브 채널에서 함께 따라할 수 있습니다. 유튜브 채널도 확인해 주세요.

YouTube Video