자바스크립트 배열, 깊게 파고들기

Hushed_Mind·2025년 4월 13일

JavaScript

목록 보기
4/7
post-thumbnail

우리는 흔히 배열을 단순한 리스트로 생각한다.
하지만 자바스크립트에서의 배열은 생각보다 더 독특한 구조와 동작 원리를 가지고 있다.
이번 글에서는 배열을 '메서드 모음집'으로 보지 않고, 자료구조 그 자체로서 깊이 있게 탐구해보자.


배열은 사실 객체(Object)다

typeof [1, 2, 3]; // "object"

자바스크립트의 배열은 사실 객체다.
정확히 말하면, 숫자 형태의 문자열을 키로 가지는 특수한 객체이다.

즉,

const arr = [1,2,3];
arr[0] === arr["0"]; // true

배열의 인덱스는 내부적으로 문자열 키 "0", "1"처럼 처리 된다.
이러한 구조는 자바스크립트 배열이 연속된 메모리 공간에 값을 저장하는 C 스타일 배열과는 다르다는 것을 보여준다.


배열 인덱스는 사실 키

우리가 arr[2]라고 쓰는 것조차 사실은 아래와 같은 의미다

arr["2"]

자바스크립트는 배열이든 객체든 모든 프로퍼티를 문자열 키로 저장한다
배열이라고 해서 예외는 아니다. 다만, 배열은 이 키 중 정수형 문자열만 인덱스로 간주하고 특별하게 다룬다.


희소 배열(Sparse Array)

아래 예제를 보자

const a = [];
a[10] = "hello";
console.log(a); // [<10 empty items>, 'hello']

이 배열은 실제로 10개의 요소를 갖는 배열이 아니다.
중간의 값은 존재하지 않고, 메모리에도 존재하지 않는 "구멍(empty slot)"으로 남는다.

이런 배열을 희소 배열(Sparse Array)이라고 부른다.
희소 배열은 순회 시 조심해야 한다. forEach, map 등은 빈 슬롯을 건너뛰지만, for, for...in은 그렇지 않다.

a.forEach((v) => console.log(v)); // "hello"만 출력

length 의 의미

자바스크립트 배열의 length요소의 개수를 말하지 않는다.
정확히는 "가장 큰 인덱스 + 1"을 의미한다.

const b = [];
b[3] = "a";
console.log(b.length); // 4

length를 조작할 수도 있다.

const c = [1,2,3,4,5];
c.length = 2;
console.log(c); // [1,2]

length를 줄이면 요소가 제거되고,
늘리면 요소가 생기지 않고 빈 슬롯만 만들어진다.

c.length = 10;
console.log(c); // [1,2, <8 empty items>]

배열은 "진짜 배열"이 아니다

C나 Java의 배열은 연속된 메모리 공간에 값이 저장된다.
하지만 자바스크립트 배열은 그렇지 않다.

배열 요소들은 메모리상 연속적으로 존재하지 않아도 된다.

때문에 arr[1000000] = 1 같은 코드도 즉시 실행된다.
왜냐하면 단순히 "1000000"이라는 키를 객체에 추가하는 일이기 때문이다.


배열이 성능에 나쁜 영향을 줄 수도 있다

V8 엔진(Chrome)은 성능을 위해 배열을 3가지 모드로 최적화한다
1. Packed Element : 연속된 인덱스에 값이 차 있는 배열
2. Holey Element : 중간에 빈 슬롯이 있는 배열
3. Dictionary Element : 배열이 너무 희소하거나 인덱스가 매우 클 때

const x = [1,2,3] // Packed
x[100] = "hi" // Holey -> Dictionary로 퇴화 가능

자바스크립트의 배열은 단순한 리스트가 아니다.
진짜 배열을 흉내 내는 객체이며, 객체의 유연함과 배열의 편리함을 동시에 제공하는 자료구조이다.
하지만 내부 구조를 모르고 무작정 사용하면,
엔전 최적화를 깨뜨리고, 퍼포먼스를 망칠 수도 있다.

다음에는 배열과 객체의 메모리 관리 차이, 배열 메서드 실제 구현 방식 등도 정리를 해보자!

profile
개발 공부 블로그

0개의 댓글