![Array[index] 사용을 그만둬라 애송이](https://w.wallhaven.cc/full/d5/wallhaven-d5gz5g.jpg)
이 포스트는 Timotius Sitorus가 자신의 dev.to 블로그에 올린 Stop using Array[index], use Array.at() instead 게시글을 번역한 것이다. 번역하는 과정에서 다소 의역이 있을 수 있으며, 일부 번역에는 사견이 포함되어있기도 하다.
Array.at() 메소드는 ECMAscript2022를 통해 새롭게 추가된 Array 생성자의 프로토타입 메소드입니다. 이 메소드를 통해 우리는 마침내 JS에서 기본적으로 Negative Indexing을 처리할 수 있게 되었습니다.
Negative Indexing
네거티브 인덱싱이라 함은 음수를 인덱스로 사용하여 배열의 시작이 아닌 끝에서부터 특정 요소에 엑세스하는 기능입니다. 예를 들어 파이썬에서는 배열의 마지막 요소에 접근하고 싶은 경우 list[-1]과 같은 방식으로 작업을 수행할 수 있습니다.
그러나 JS의 array는 이런 식으로 작동하지 않습니다. 대괄호 표기법이 array나 string에 속한 것이 아니라 모든 object에 속하기 때문에 ─ 이 부분에 대해서 따로 확인해본 것은 아니지만 이러한 표기법을 지원하는 프로퍼티가 object 생성자의 prototype에 존재하는 것이 아닐까 추측한다 ─ 그렇습니다.
object에서 대괄호 표기법을 사용할 경우 해당 key를 사용하여 객체의 value를 얻는 것을 의미합니다. 배열과 문자열 역시 객체이기 때문에, 이러한 자료형들에서도 동일한 작동을 보이는 것입니다. 내부적으로 배열과 문자열은 각 요소를 현재 인덱스와 일치하는 키에 할당합니다.
// 인덱싱 방식에 관해서라면 arr는 obj와 완전히 동일하게 동작한다
const arr = ['cat', 'dog', 'fish', 'bird'];
const obj = {
0: 'cat',
1: 'dog',
2: 'fish',
3: 'bird'
};따라서 arr[-1]은 이미 유효한 JS이지만 마지막 요소를 반환하는 것이 아닌 배열의 "-1" key에 해당하는 value를 반환하려고 시도합니다. 그리고 이러한 경우 JS는 당연하게도 ─ "-1" key가 없으니 ─ undefined를 반환하게 될 것입니다.
기존의 해결 방법
기존 JS에서는 네거티브 인덱싱을 지원하지 않지만, 이를 흉내내는 기법 몇 가지가 널리 알려져있습니다. 아마도 가장 유명한 기법은 배열의 길이에서 음수 인덱스만큼 뺀 값을 사용하는 것입니다.
const pets = ['cat', 'dog', 'fish', 'bird'];
const lastPet = pets[pets.length - 1];
console.log(lastPet); // Prints out 'bird'대부분의 개발자가 네거티브 인덱싱을 흉내내기 위해 사용하는 기법이지만, 여기에는 몇 가지 문제가 있습니다.
배열의 이름이 두 번 호출되며, 일반적으로는 꽤 길어집니다.
변수에 할당되지 않은 배열에는 사용할 수 없습니다.
임시 변수에 저장하지 않는 한 함수가 리턴하는 마지막 값을 쓸 수 없습니다.
['cat', 'dog', 'fish', 'bird'][ **what do you put here** - 1];
const a = () => ['cat', 'dog', 'fish', 'bird'];
a()[ **What do you out here** - 1];다른 방식으로는 Array.slice() 메소드가 네거티브 인덱싱을 지원한다는 점을 이용할 수 있습니다.
const pets = ['cat', 'dog', 'fish', 'bird'];
const lastPet = pets.slice(-1)[0];
console.log(lastPet); // Prints out 'bird'이 방법은 앞서 언급한 많은 문제를 해결하지만, 몇 가지 새로운 문제를 일으킵니다.
구문을 직관적으로 이해하는 데 어려움이 있습니다. 특히 네거티브 인덱싱으로 slice된 array에 [0]이 꼬리를 물고 붙어있다는 점이 그렇습니다.
지정한 인덱스로부터 배열의 끝까지가 임시 배열을 이루게 됩니다. 이는 [0]을 통해 원하는 item을 리턴한 이후 메모리 힙에서 즉시 삭제됩니다.
Array.at()
at 메소드는 위에서 언급한 다양한 문제를 해결하기 위해 구현되었습니다. 아규먼트로 양수를 넣을 경우 Array[index]와 정확히 동일한 작동을 보장하면서, 아규먼트로 음수를 넣는 경우에는 네거티브 인덱싱을 완벽하게 구현해냅니다.
const pets = ['cat', 'dog', 'fish', 'bird'];
const lastPet = pets.at(-1);
console.log(lastPet); // Prints out 'bird'이 메소드를 사용하므로써 네거티브 인덱싱을 흉내내는 이전의 방식들을 대체할 수 있으며, 더 깔끔한 구문을 제공하며, 성능 저하가 발생하지도 않습니다. 필요한 경우 polyfill을 사용할 수 있으며, 대부분의 최신 브라우저에서 at 메소드를 사용할 수 있습니다.
더 읽어보기
2026.04.11
Trie 자료구조
문자열 데이터를 다룰 때 단순히 “이 단어가 있나?”만으로는 부족한 순간이 있다. 자동 완성처럼 특정 접두사로 시작하는 후보를 모아야 할 때도 있고, 어떤 키에 값을 두고 빠르게 찾고 싶을 때도 있다. 이럴 때 가장 자연스럽게 떠올릴 수 있는 자료구조가 바로 Trie이다. Trie는 무…
2026.03.19
Streams API 부록 2. 왜 이미지는 위에서 아래로 나타날까
느린 네트워크에서 큰 이미지를 열면 가끔 화면이 위에서 아래로 채워진다. 마치 누군가 아주 성실하게 롤러로 이미지를 칠하는 것처럼 보인다. 물론 브라우저 안에 그런 직원은 없다. 있다면 우리보다 야근을 더 많이 하고 있을 것이다. 이 현상은 단순한 시각 효과가 아니라 네트워크 전송, 브…
2026.03.19
Streams API 부록 1. HTTP 다운로드 진행률은 어떻게 계산될까
다운로드 화면에서 진행 막대가 조금씩 차오르면 이상하게 안심된다. 반대로 스피너만 계속 돌면 파일이 오는 중인지, 서버가 고민 중인지, 내 인생이 잠깐 멈춘 건지 알 수 없다. 사용자는 둘 다 “다운로드 중”이라고 느끼지만, 내부적으로는 꽤 다른 상황일 수 있다. 진행률 계산 자체는 복…
2026.03.13
Streams API 4. 왜 모든 언어에는 Stream API가 존재할까
Streams API를 공부하다 보면 묘한 기시감이 온다. JavaScript에서 ReadableStream, WritableStream, TransformStream을 보고 있는데, Java의 InputStream, Go의 io.Reader, Rust의 Read와 Write가 멀리서…
2026.06.01
React Server Components를 위한 컴포넌트 아키텍처
이 포스트는 Vercel의 Next.js 팀 소속 개발자 Aurora Scharff가 자신의 블로그에 올린 Component Architecture for React Server Components 게시글을 번역한 것이다. 번역하는 과정에서 다소 의역이 있을 수 있으며, 일부 번역에는…
2026.05.26
차트는 멈췄는데 윈도우가 움직인다
상황 어느날 서비스를 살펴보시던 팀장님께서 이런 말씀을 slack에 남기셨다. 진호님, 예측 차트에서 zoom을 계속하면 어느 순간 라인 차트가 아니라 단일 스캐터 차트처럼 보이는 데, 이거 수정하면 좋을 거 같아요. 어느정도 zoom을 하면 그 이후로는 zoom이 안 되도록 할 수 없…
2026.05.21
피자가게로 이해하는 디자인 패턴
에이든 피자는 처음부터 복잡한 시스템을 만들 생각이 없었다. 처음에는 메뉴 몇 개만 만들면 됐다. 그런데 손님은 커스텀 주문을 넣기 시작했고, 주방은 상태를 나눠야 했고, 결제와 배달앱과 알림이 하나씩 붙었다. 코드도 가게를 닮는다. 장사가 잘될수록 이상하게 더 쉽게 망가진다. 디자인…
2026.05.21
7. Decorator — 토핑 추가할 때마다 클래스를 새로 만들 수 없다
에이든 피자에서 주문서를 객체로 만들자 취소와 재주문은 한결 편해졌다. 그런데 주문이 편해지자 손님들도 한결 편해졌다. 편해진 손님은 더 많은 요구를 한다. "치즈 추가요", "올리브도 추가요", "소스 많이요", "조금 더 바삭하게 구워주세요" 같은 요청이 주문대 위로 쌓이기 시작했다…
댓글
댓글을 불러오는 중...