Menu

자바스크립트 배열 완벽 정리: 생성부터 반복까지

자바스크립트에서 배열을 만들고, 인덱스로 접근하고, push/pop으로 수정하고, slice와 splice를 구분해서 쓰는 방법까지 실무에서 바로 쓸 수 있게 정리했습니다.

자바스크립트 배열이란?

자바스크립트 배열(array)은 값들을 순서대로 담아두는 자료구조입니다. 담는 값의 타입은 자유로워서 숫자, 문자열, 객체는 물론 또 다른 배열까지 넣을 수 있고, 같은 타입으로 통일하지 않아도 됩니다. 배열을 만들 때는 대괄호를 쓰면 됩니다:

index.js
Output
Click Run to see the output here.

배열 리터럴([]) 문법은 실제로 배열을 만들 때 99% 쓰게 되는 방식입니다. new Array(...)라는 방법도 있긴 한데, 함정이 하나 숨어 있어요. new Array(3)이라고 쓰면 [3]이 아니라 길이만 3이고 실제 요소는 하나도 없는 배열이 만들어집니다. 그냥 []만 쓰는 걸 추천합니다.

인덱스는 0부터 시작합니다

자바스크립트 배열은 위치(인덱스)로 요소에 접근하는데, 이 인덱스가 0부터 시작합니다:

index.js
Output
Click Run to see the output here.

여기서 두 가지를 짚고 넘어갈 필요가 있습니다. 첫째, 배열 범위를 벗어난 인덱스로 접근해도 에러가 나지 않고 undefined를 돌려줍니다. "왜 자꾸 undefined가 나오지?" 하는 버그의 단골 원인이 바로 이거죠. 둘째, 아무 인덱스에나, 심지어 배열 끝보다 한참 뒤쪽 인덱스에도 값을 할당 할 수 있는데, 자바스크립트는 군말 없이 배열을 늘려줍니다:

index.js
Output
Click Run to see the output here.

인덱스 3번과 4번 자리는 "빈 슬롯(sparse hole)"이 됩니다. length는 6으로 훌쩍 뛰고요. 사실 이런 상황은 일부러 만들 일이 거의 없습니다. 자바스크립트 배열이 워낙 유연하다 보니 생기는 부작용일 뿐, 믿고 쓸 만한 동작은 아니에요.

자바스크립트 배열 length는 실시간으로 바뀐다

array.length는 항상 가장 큰 인덱스보다 1 큰 값을 가집니다. 요소를 추가하거나 제거하면 자동으로 갱신되죠.

index.js
Output
Click Run to see the output here.

방금 본 트릭은 꼭 기억해두세요. length에 값을 대입하면 배열이 잘려 나갑니다. nums.length = 0으로 설정하면 배열을 그 자리에서 비워버리는 빠른 방법이죠.

push, pop, shift, unshift

배열 양 끝에서 요소를 추가하거나 제거할 때 쓰는 네 가지 메소드입니다:

index.js
Output
Click Run to see the output here.
  • push(x)는 배열 끝에 값을 추가하고, 새로운 length를 반환합니다.
  • pop()은 끝에서 값을 꺼내 반환합니다.
  • unshift(x)는 배열 맨 앞에 값을 추가합니다.
  • shift()는 맨 앞에서 값을 꺼냅니다.

pushpop은 빠릅니다. 반면 shiftunshift는 나머지 요소들의 인덱스를 전부 다시 매겨야 해서 배열이 커질수록 느려집니다. 일상적인 크기에서는 신경 쓸 필요 없지만, 수백만 개를 다룬다면 기억해 둘 만한 포인트예요.

slice와 splice 차이

이름은 비슷한데 동작은 완전히 다른 둘입니다. 이 차이만 확실히 잡아두면 나중에 머리 싸맬 일이 훨씬 줄어듭니다.

slice(start, end)는 배열의 일부를 복사해서 돌려줍니다. 원본은 건드리지 않고요. end는 포함되지 않는다는 점도 기억해 두세요:

index.js
Output
Click Run to see the output here.

splice(start, deleteCount, ...items)는 원본 배열을 직접 변경 합니다. 요소를 지울 수도, 새로 끼워 넣을 수도, 아니면 둘 다 할 수도 있고, 제거된 요소들은 반환값으로 돌려줍니다:

index.js
Output
Click Run to see the output here.

팁 하나. 빵 한 덩어리에서 한 조각을 잘라내는 느낌이면 slice, 필름을 자르고 이어 붙이는 느낌이면 splice라고 기억하면 헷갈리지 않습니다.

배열에서 값 찾기: indexOf, includes, find

상황에 따라 골라 쓸 수 있는 세 가지 검색 방법을 살펴보겠습니다.

index.js
Output
Click Run to see the output here.
  • indexOf(x)는 해당 요소의 인덱스를 돌려주고, 없으면 -1을 반환합니다. 위치 값이 필요할 때 쓰기 좋습니다.
  • includes(x)는 불리언(boolean)을 반환합니다. 그냥 "이 값이 들어 있나?"만 확인하고 싶을 때 더 깔끔하죠. 덤으로 NaN도 제대로 처리해 주는데, indexOf는 이걸 못 잡아냅니다.
  • find(predicate)는 각 요소마다 함수를 실행해서 조건에 맞는 첫 번째 요소를 돌려줍니다. 객체 배열을 다룰 때 꼭 필요한 메소드인데, indexOfincludes는 엄격한 동등 비교만 하기 때문입니다.

자바스크립트 배열 반복문 돌리기

상황별로 알맞게 쓸 수 있는 몇 가지 방법이 있습니다:

index.js
Output
Click Run to see the output here.

for...of는 기본값으로 쓰기 좋은 반복문이다. 읽기 편하고, 어떤 이터러블(iterable)에도 동작하며, 값을 바로 꺼내준다. 인덱스까지 같이 쓰고 싶고 중간에 루프를 빠져나올 일이 없다면 forEach도 괜찮다 (참고로 forEach 안에서는 break를 쓸 수 없다). 인덱스를 쓰는 고전적인 for문은 장황하긴 해도 제어권이 완전히 내 손에 있다. 요소를 건너뛰거나 역순으로 순회해야 할 때, 혹은 둘 다 필요할 때 쓰면 된다.

피해야 할 반복문이 하나 있다. 바로 for...in이다. 이건 _키_를 순회하는 데다 상속받은 프로퍼티까지 끌려 나온다. 객체용이지 배열용이 아니다.

배열 복사와 합치기

자바스크립트 배열은 참조값(reference)이다. 한 배열을 다른 변수에 대입해도 복사가 되는 게 아니라, 같은 배열을 가리키는 이름이 하나 더 생기는 것뿐이다:

index.js
Output
Click Run to see the output here.

진짜로 복사하려면 스프레드 연산자나 slice()를 써야 합니다:

index.js
Output
Click Run to see the output here.

둘 다 얕은 복사(shallow copy)를 만들어 줍니다. 최상위 배열은 새로 만들어지지만, 요소가 객체라면 그 객체들은 여전히 원본과 공유됩니다. 스프레드 문법은 배열을 합칠 때도 가장 깔끔한 방법이죠:

index.js
Output
Click Run to see the output here.

객체로 이루어진 배열 다루기

실제 프로젝트에서는 대부분의 배열이 객체를 담고 있습니다. 앞서 배운 자바스크립트 배열 메소드들은 그대로 쓸 수 있지만, 조건을 매칭하는 부분이 훨씬 재미있어집니다:

index.js
Output
Click Run to see the output here.

filter는 조건(predicate)에 맞는 요소들만 뽑아 새 배열로 돌려주고, map은 각 요소를 변환해서 새 배열을 만들어 줍니다. 이 둘을 체이닝하는 건 객체 배열을 다룰 때 그야말로 밥 먹듯이 쓰는 패턴이에요. 다음 문서에서는 이런 배열 메소드들을 좀 더 깊이 있게 살펴봅니다.

배열과 객체, 언제 뭘 쓸까

간단하게 구분해 볼게요. 순서가 중요하고 같은 종류의 목록 을 다룰 때는 배열을 씁니다. 반대로 이름(키)로 값을 찾아야 할 때는 객체(또는 Map)를 쓰세요. "첫 번째, 두 번째, 세 번째" 같은 상황은 배열의 영역이고, "id가 42인 사용자를 찾아라" 같은 상황은 객체나 Map의 영역입니다.

물론 둘을 섞어서 쓸 수도 있어요. 객체들이 담긴 배열은 어디서나 볼 수 있죠. 다만 배열을 키 기반 사전처럼 쓰거나, 객체를 순서 있는 리스트처럼 쓰는 건 피하는 게 좋습니다. 각자 잘하는 역할이 따로 있거든요.

다음 주제: 구조 분해 할당

배열에서 인덱스로 값을 꺼내거나 객체에서 이름으로 속성을 꺼내는 일은 정말 자주 등장합니다. 그래서 자바스크립트에는 이걸 위한 전용 문법이 따로 마련돼 있어요. 바로 구조 분해 할당(destructuring) 인데, 다음 글에서 바로 이어집니다.

자주 묻는 질문

자바스크립트에서 배열은 어떻게 만드나요?

대괄호 리터럴 문법이 가장 흔히 쓰는 방식입니다. const fruits = ['apple', 'banana'] 이런 식이죠. new Array(3) 같은 Array 생성자도 있긴 한데, 실제 요소 없이 길이만 3인 빈 배열이 만들어져서 의외로 헷갈리는 경우가 많으니 되도록 쓰지 않는 게 좋습니다.

자바스크립트 배열에서 특정 요소를 제거하려면 어떻게 해야 하나요?

끝에서 빼려면 pop(), 맨 앞에서 빼려면 shift()를 씁니다. 중간에 있는 요소를 지우려면 원본을 직접 수정하는 splice(index, 1)을 쓰거나, 해당 요소만 빠진 새 배열을 얻고 싶다면 filter(...)를 쓰면 됩니다. splice는 원본을 바꾸고, filter는 그대로 둔다는 점만 기억하세요.

slice와 splice는 뭐가 다른가요?

slice(start, end)는 배열의 일부를 얕은 복사해서 새 배열로 반환하고 원본은 건드리지 않습니다. 반면 splice(start, deleteCount, ...items)는 원본을 직접 수정해서 요소를 제거하고, 필요하면 새 요소를 끼워 넣은 뒤 제거된 요소들을 반환합니다. 글자 하나 차이지만 동작은 완전히 다르니 주의해야 합니다.

자바스크립트 배열에 특정 값이 들어 있는지 확인하려면요?

array.includes(value)를 쓰면 true 또는 false를 반환하고, NaN도 제대로 처리해줍니다. 위치까지 알고 싶다면 indexOf(value)를 써서 인덱스(없으면 -1)를 받으면 되고요. 객체 배열처럼 조건 비교가 필요하면 some(predicate)이나 find(predicate)를 쓰는 게 훨씬 깔끔합니다.

Coddy로 코딩 배우기

시작하기