배열 vs 객체
애플리케이션에서 데이터를 다룰 때에는 데이터의 용도에 맞게 적절한 자료구조를 사용해야 합니다. 배열과 객체는 모두 대량의 데이터를 다룰 때 활용할 수 있는 자료구조이며, (사실 자바스크립트에서는 배열도 객체입니다만) 내장 메서드를 활용하면 간단하게 양쪽 간에 형태를 서로 변환할 수 있습니다.
형태를 변환해주어야 하는 경우의 예로는 외부에서 가져온 데이터의 구조가 애플리케이션과 궁합이 맞지 않는 경우, 자체적으로 구현한 자료구조라고 하더라도 형식을 변환해 줌으로써 순간적인 성능 향상의 이점을 얻을 수 있는 경우 등이 있습니다.
배열을 객체로 바꿔줘야 하는 경우
배열 내의 특정 요소에 접근하기 위해서는 우선 모든 요소들을 순회해야합니다. 이때 배열 내의 각 요소를 특정할 수 있는 수단은 index밖에 없기 때문에 해당하는 index를 모르는 상태라면 필연적으로 첫번째부터 배열의 요소를 순회해야 한다는 단점이 있습니다(BFS, DFS 등의 알고리즘은 본 글의 주제를 벗어나므로 다루지 않겠습니다).
또한 index를 알고 있는 경우라고 하더라도 그 index를 뽑아내기 위해서 사전에 이미 배열의 요소들을 순회한 셈이므로 동일한 성능상의 손해가 있었다고 볼 수 있습니다.
이러한 단점 때문에 길이가 크고 각 요소로의 접근이 잦은 배열이라면 객체로 변환한 후에 사용하는 것이 좋습니다.
예시
코드를 통해서 살펴보겠습니다.
배열과 객체 각각 내부의 데이터에 접근하면서 수행시간을 측정하겠습니다.
1. 배열
let arr = [];
for (let i = 1; i <= 10000000; i++) {
arr.push({
id: i,
name: `사람 ${i}번`
});
}
console.log(arr);
/*
[
{ id: 1, name: '사람 1번' },
{ id: 2, name: '사람 2번' },
{ id: 3, name: '사람 3번' },
{ id: 4, name: '사람 4번' },
{ id: 5, name: '사람 5번' },
{ id: 6, name: '사람 6번' },
{ id: 7, name: '사람 7번' },
{ id: 8, name: '사람 8번' },
{ id: 9, name: '사람 9번' },
...
{ id: 10000000, name: '사람 10000000번' }
]
*/
id와 name property를 갖고 있는 객체의 배열입니다. 길이는 1000만으로 설정했습니다.
위 배열에서 id가 800만 인 객체에 접근하고 수행시간을 측정해 보겠습니다.
console.time("search time - array");
const target = arr.find(value => value.id === 8000000);
console.timeEnd("search time - array");
5번의 실행결과는 아래와 같습니다. 실행환경은 node입니다.
search time - array: 99.548ms
search time - array: 96.498ms
search time - array: 91.824ms
search time - array: 95.571ms
search time - array: 100.882ms
평균적으로 97ms 소요되었습니다.
2. 객체
let obj = {};
for (let i = 1; i <= 10000000; i++) {
obj[i] = {
id: i,
name: `사람 ${i}번`
};
}
/*
{
'1': { id: 1, name: '사람 1번' },
'2': { id: 2, name: '사람 2번' },
'3': { id: 3, name: '사람 3번' },
'4': { id: 4, name: '사람 4번' },
'5': { id: 5, name: '사람 5번' },
'6': { id: 6, name: '사람 6번' },
'7': { id: 7, name: '사람 7번' },
'8': { id: 8, name: '사람 8번' },
'9': { id: 9, name: '사람 9번' },
...
'10000000': { id: 10000000, name: '사람 10000000번' }
}
*/
id와 name property를 갖고 있는 객체들을 이번에는 각 id를 key로 하는 내부 객체의 형태로 구현하였습니다.
동일하게 id가 800만 인 내부 객체에 접근하고 수행시간을 측정해 보겠습니다.
console.time("search time - object");
const target = obj["8000000"];
console.timeEnd("search time - object");
5번의 실행결과는 아래와 같습니다.
search time - object: 0.265ms
search time - object: 0.224ms
search time - object: 0.253ms
search time - object: 0.218ms
search time - object: 0.243ms
평균적으로 0.24ms 소요되었습니다.
결과
배열 | 97ms | 복잡도 O(n) |
객체 | 0.24ms | 복잡도 O(1) |
객체에서 내부 객체를 찾는 경우에는 모든 객체의 주소가 key값으로 특정되어 있기 때문에 실행 즉시 메모리에서 값을 찾아옵니다(O(1)).
따라서 배열에서 자료를 지속적으로 찾아야 하는 경우에는 배열을 객체로 전환한 후 작업을 진행하면 시간복잡도 O(1)를 유지할 수 있습니다.
3. 배열을 객체로 변환하는 방법
아래는 배열을 객체로 변환하는 다양한 예시들입니다.
const obj = {};
for (let i = 0; i < arr.length; i++) {
obj[arr[i].id] = arr[i];
}
const obj = {};
arr.forEach(value => (obj[value.id] = value));
const obj = arr.reduce((obj, cur) => {
obj[cur.id] = cur;
return obj;
}, {});
const obj = Object.assign({}, ...arr.map(value => ({ [value["id"]]: value })));
'자바스크립트' 카테고리의 다른 글
[JAVASCRIPT] this가 가리키는 객체 (메서드, 함수, 화살표 함수에서) (4) | 2024.01.05 |
---|---|
[JAVASCRIPT] 문자열이 특정 문자열로 시작하는지(or 끝나는지) 확인하는 방법 - startsWith(), endsWith() (1) | 2024.01.03 |
[JAVASCRIPT] 랜덤 숫자(난수) 생성하는 방법 - Math.random() (0) | 2023.12.28 |
[JAVASCRIPT] 캐싱 함수 만들기 / 데코레이터(decorator) (1) | 2021.08.30 |
[JAVASCRIPT] 중첩 객체에서 특정 프로퍼티의 합 구하기, 재귀함수 활용 (0) | 2021.08.19 |