JavaScript에서 객체 배열 두 개를 특정 키(예: id)를 기준으로 하나로 합쳐야 하는 경우가 자주 있습니다. 예를 들어, 한 배열에는 사용자의 id와 이름이 담겨 있고, 다른 배열에는 사용자의 id와 주소가 담겨 있다고 가정해 보겠습니다.
const arr1 = [
{"id":"123","name":"name 1"},
{"id":"456","name":"name 2"}
];
const arr2 = [
{"id":"123","address":"address 1"},
{"id":"456","address":"address 2"}
];문제 정의
우리는 이렇게 구성된 두 개의 배열을 인자로 받아, 세 번째 배열을 만들어 반환하는 JavaScript 함수를 작성해야 합니다. 결과 배열의 각 객체에는 해당 사용자의 id, name, address가 모두 포함되어야 합니다.
해결 방법
가장 간단한 접근 방식은 map()과 findIndex()를 조합하는 것입니다. 첫 번째 배열을 순회하면서 각 객체와 동일한 id를 가진 요소를 두 번째 배열에서 찾고, 찾은 주소 정보를 스프레드 연산자(...)로 병합하면 됩니다.
const arr1 = [
{"id":"123","name":"name 1"},
{"id":"456","name":"name 2"}
];
const arr2 = [
{"id":"123","address":"address 1"},
{"id":"456","address":"address 2"}
];
const mergeArrays = (arr1 = [], arr2 = []) => {
let res = [];
res = arr1.map(obj => {
const index = arr2.findIndex(el => el["id"] == obj["id"]);
const { address } = index !== -1 ? arr2[index] : {};
return {
...obj,
address
};
});
return res;
};
console.log(mergeArrays(arr1, arr2));실행 결과
콘솔에 출력되는 결과는 다음과 같습니다.
[
{ id: '123', name: 'name 1', address: 'address 1' },
{ id: '456', name: 'name 2', address: 'address 2' }
]동작 원리 살펴보기
map()은 첫 번째 배열(arr1)의 각 객체를 순회하며 새로운 배열을 생성합니다.findIndex()는 두 번째 배열(arr2)에서 현재 객체와 같은id를 가진 요소의 위치를 찾습니다. 일치하는 요소가 없으면-1을 반환합니다.- 일치하는 요소가 존재하면 그 객체에서
address값을 추출하고, 없으면 빈 객체를 구조 분해하여undefined가 되도록 처리합니다. 이 덕분에 매칭되는 데이터가 없어도 오류 없이 안전하게 동작합니다. - 마지막으로 스프레드 연산자로 기존 객체의 속성과
address를 합쳐 새로운 객체를 반환합니다.
성능 개선 팁
위 방법은 직관적이지만, findIndex()가 배열을 처음부터 끝까지 탐색하기 때문에 시간 복잡도가 O(n×m)입니다. 데이터 양이 많다면 두 번째 배열을 Map으로 변환해 조회하면 O(n+m)으로 최적화할 수 있습니다.
const mergeArraysOptimized = (arr1 = [], arr2 = []) => {
const map = new Map(arr2.map(obj => [obj.id, obj.address]));
return arr1.map(obj => ({ ...obj, address: map.get(obj.id) }));
};대용량 데이터를 다룰 때는 이처럼 해시 기반 조회를 활용하면 성능을 크게 향상시킬 수 있습니다.