JavaScript 배열이 그 배열이 아니에요

moontag·2024년 6월 20일
1

JavaScript 배열과 그 배열의 차이점

먼저 자료구조나 전통적인 정적 배열을 사용하는 언어들(C, C++, Java)의 배열과 Javascript의 배열의 구현과 동작이 다르다.

자료구조 배열

: 밀집 배열(dense array)

  • 정적 배열. 고정된 배열 길이
  • 연속적인 데이터 배치
  • 같은 타입 데이터 저장
  • 시간 복잡도
    1. 삽입/삭제 느림 - O(N) : 해당 index의 데이터 삽입/삭제 후 그 뒤 요소들을 밀거나/당겨와야 하기 때문
    2. 검색 빠름 - O(1) : 해당 index 데이터 출력 (배열이 정렬되지 않았다면 O(N))




JavaScript 배열

: 배열의 동작을 구현한 객체

  • 동적 배열. 가변적인 배열 길이
  • 비연속적인 데이터 배치 - 희소 배열(sparse array) 허용하기 때문
  • 다양한 타입 데이터 저장 (숫자, 문자열, 객체 등 다양한 타입 혼합가능)
  • 시간 복잡도
    1. push, pop - O(1) : 맨 마지막 요소만 변경하면 되기 때문
    2. shift, unshift - O(N) : 맨 앞 요소 변경하면 나머지 요소들을 밀거나/당겨와야 하기 때문
    3. 특정값 검색 느림 - O(N) : 순차적으로 접근(선형검색)하기 때문

희소 배열

: 배열의 일부 요소가 비어있는 배열. [1, empty × 2]

const arr = [1];
arr.length = 3;
console.log(arr);         // [1, empty × 2]
console.log(arr.length);  // 3
console.log(arr[1]); // undefined
console.log(Object.getOwnPropertyDescriptors(arr));
// {
//   0 : {value: 1, writable: true, enumerable: true, configurable: true}
//   length : {value: 3, writable: true, enumerable: false, configurable: false} 
// }

배열 길이보다 length에 더 큰값 할당 시 length 프로퍼티 값은 변경됨
하지만 실제 배열엔 empth로 값이 할당되지 않음.
=> 배열의 중간이 비어있는 희소 배열

최적화

  • JIT(Just-In-Time) 컴파일러 최적화
    JavaScript 엔진은 배열에 모두 같은 타입의 데이터만 있다면 연속적으로 메모리 할당하고
    JIT 컴파일러는 이런 배열에 대해 C 컴파일러와 같은 배열 계산 수행.
  • 하지만 다른 타입 데이터 들어가면, 비연속적인 메모리 할당한다.

연속성과 고정된 데이터 타입의 구조를 사용하고 싶다면, ArrayBuffer와 TypedArray 사용하면 된다

ArrayBuffer

: 연속적인 데이터 보관하는 메모리 공간 영역 (바이너리 데이터. 바이트로 구성된 배열)

  • 고정된 길이.
  • 데이터를 직접 조작하려면 TypedArrayDataView 객체 사용. ArrayBuffer의 할당된 공간은 특정타입의 데이터로 조회, 쓰기 가능.

TypedArray

: 타입 지정된 배열

  • ArrayBuffer에 데이터를 수정할 때 사용
  • 타입 종류
    Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array
  • Int8Array : 정수타입을 가진 각 요소가 8비트인 배열
const buffer = new ArrayBuffer(8); // 버퍼의 크기 8 = 8 bytes

const int8arr = new Int8Array(buffer); // 각 요소의 크기는 8bits === 1byte이므로 길이가 8인 Int8Array가 생성
const int16arr = new Int16Array(buffer); // 16비트(2바이트) 정수 타입

console.log(int8arr); // Int8Array [0, 0, 0, 0, 0, 0, 0, 0] : 8개 0으로 초기화된 요소
console.log(int16arr); // Int16Array [0, 0, 0, 0]           : 4개의 0으로 초기화된 요소


사용처

WebGL 3D를 다루는 Three.js에서는 내부적으로 TypedArray 사용.

  • 대용량 데이터 처리 시 메모리 사용 효율적
  • 바이너리 데이터로 컴퓨터가 직접 처리할 수 있어서 연산 빠름

참고

JavaScript 배열(Array)의 발전과 성능에 대해서 자세히 알아보기 - Evans

profile
터벅터벅 나의 개발 일상

0개의 댓글