자바스크립트 배열

Jemin·2024년 12월 23일
0

개발 지식

목록 보기
52/53

왜인지 저는 자바스크립트 배열은 연결 리스트로 구현되어 있다고 생각하고 있었습니다. 그런데, 오늘 아침 매일메일에서 받은 질문의 답변을 확인해보니 생각했던 것과는 달라서 다시 찾아보게 되었습니다.

자바스크립트 배열의 특성

제가 찾아본 자바스크립트 배열은 다음과 같은 특성을 가지고 있습니다.

  • 자바스크립트 객체입니다.

  • 해시 테이블로 구현된 객체입니다.

  • 일반적으로 연속된 값의 리스트, 즉 밀집 배열입니다. 하지만, 희소 배열이 될 수도 있습니다.

  • 배열의 크기가 고정되지 않고 동적으로 크기가 변할 수 있습니다.

  • 요소를 인덱스로 접근할 수 있습니다.

  • 0 인덱스입니다. 배열의 첫 번째 요소는 인덱스 0에 위치합니다.

  • 연관 배열이 아닙니다.

위 특성들을 좀 더 자세하게 살펴보겠습니다.

자바스크립트 객체

모던 자바스크립트에서 자바스크립트의 배열은 다음과 같이 설명합니다.

일반적 의미의 배열이 아닌 일반적인 배열의 동작을 흉내 낸 특수한 객체

console.log(Object.getOwnPropertyDescriptors([1,2 , 3]));
/*
{
  '0': { value: 1, writable: true, enumerable: true, configurable: true },
  '1': { value: 2, writable: true, enumerable: true, configurable: true },
  '2': { value: 3, writable: true, enumerable: true, configurable: true },
  length: { value: 3, writable: true, enumerable: false, configurable: false }
}
*/

위 코드의 결과처럼 배열은 인덱스를 나타내는 문자열을 프로퍼티 키로 가지며, length 프로퍼티를 갖는 특수한 객체입니다. 자바스크립트 배열의 요소는 사실 프로퍼티 값이기 때문에 어떤 타입의 값이라도 배열의 요소가 될 수 있는 것입니다.

해시 테이블로 구현

자바스크립트 배열은 우리가 알던 C언어 Java와 같은 배열이 아닌 객체입니다. 이 객체는 해시테이블로 구현되어 있습니다.

해시테이블은 각각의 키 값에 해시 함수를 적용해 배열의 고유한 인덱스를 생성하고 이 인덱스를 활용해 값을 저장하거나 검색을 하는 자료구조입니다.

위 코드 결과에서 본 것처럼 자바스크립트 배열은 키 값이 숫자인 해시 테이블로 볼 수 있습니다.
자바스크립트 배열은 크기가 고정되어 있지 않고 내부 요소들의 타입이 동일하지 않을 수 있고 해시 테이블로 구현된 객체이므로 인덱스로 요소에 접근하는 경우 일반적인 배열보다 성능적인 측면에서 느릴 수 밖에 없습니다. 하지만 요소를 삽입, 삭제하는 경우에는 일반적인 배열보다 빠른 성능을 기대할 수 있습니다.

밀집 배열, 희소배열

일반적인 배열들은 동일한 크기의 메모리 공간이 연속적으로 나열되어 있습니다. 이러한 배열을 밀집 배열이라고 합니다.
자바스크립트 엔진은 실제로 일반적으로 배열의 요소를 인접한 메모리 공간에 차례로 저장해둡니다. 이러한 특징 덕분에 인덱스를 이용해서 배열의 요소에 접근하는 것이 매우 빠릅니다.

검색 대상 요소의 메모리 주소 = 배열의 시작 메모리 주소 + 인덱스 * 요소의 바이트 수

하지만 자바스크립트 배열이 꼭 밀집 배열이 아니고 희소 배열일 수도 있습니다.

희소 배열이란 배열 요소의 위치가 불연속적인 배열을 의미합니다. 자바스크립트 코드로는 아래와 같은 방법으로 확인할 수 있습니다.

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

희소 배열은 위 코드 결과와 같이 자바스크립트 배열의 요소 중 값이 없는 요소가 있는 배열입니다. 이때 값이 없다는 것은 undefined가 아닌 empty로 프로퍼티 자체가 존재하지 않는 것입니다.

동적 배열

자바스크립트의 배열은 배열의 크기를 지정해서 사용해야하는 C언어, Java와는 달리 배열의 크기가 동적으로 변합니다.

먼저 자바스크립트 엔진은 배열이 생성되면 메모리의 일정 공간을 초기 크기로 예약합니다.

요소가 추가되었을 때, 현재 예약된 메모리 크기보다 크다면 새로운 메모리 공간을 재할당합니다. 기존 배열보다 더 큰 크기의 새로운 메모리 블록을 할당하고 기존 배열의 데이터를 새로운 메모리 공간으로 복사합니다. 이때 새로 할당하는 메모리의 크기는 지수적으로 증가(ex. 2배)하여 잦은 크기 변경을 방지합니다.

요소를 제거했을 때에는 크기를 줄이지 않지만, 배열의 크기가 특정 임계값 이하로 작아지면 자바스크립트 엔진이 크기를 축소할 수도 있습니다.

만약 배열의 마지막 요소가 아닌 중간에 위치한 요소를 삭제한다면 자바스크립트 엔진은 배열의 연속성을 유지하기 위해 요소를 이동시킵니다. 이때 일어나는 요소의 이동은 비용이 크기 때문에 성능적으로 문제가 발생할 수 있습니다.

인덱스로 접근

자바스크립트 배열은 0 인덱스부터 시작합니다. 배열의 첫 번째 요소는 인덱스 0에 위치합니다.

자바스크립트 엔진은 배열을 메모리에 연속적으로 저장하기 때문에 인덱스로 원하는 요소에 아주 빠른 속도로 접근할 수 있습니다. 배열의 원하는 요소를 가져오는 시간 복잡도는 O(1)입니다. 숫자 인덱스를 기반으로 하기 때문에 위치를 바로 참조할 수 있습니다.

연관 배열이 아님

연관 배열이란 자료구조 중 하나로, 키 하나와 값 하나가 연관되어 있으며 키를 통해 연관된 값을 얻을 수 있습니다.

자바스크립트 배열은 객체이지만 연관 배열이 아닙니다. 정수 인덱스 기반이기 때문에 문자열 키로는 접근하지 않습니다. 이는 자바스크립트 배열의 설계 목적이 연속적이고 순차적인 데이터 관리와 빠른 접근을 위한 것이기 때문입니다.


정리하자면, 자바스크립트 배열은 다양한 데이터 타입을 담을 수 있는 유연한 리스트형 객체(배열처럼 동작하는 객체)로, 동적 배열이라는 특징을 가지며, 요소를 추가하거나 제거할 때마다 배열 크기가 자동으로 조정됩니다.

참고
Array - JavaScript | MDN
자바스크립트 배열(Array) 완벽 정복 ❗
모던 자바스크립트 Deep Dive

profile
경험은 일어난 무엇이 아니라, 그 일어난 일로 무엇을 하느냐이다.

0개의 댓글