문제 정의
실무에서는 서로 다른 출처에서 가져온 두 개의 객체 배열을 비교하고, 특정 키(id)를 기준으로 데이터를 병합하거나 일부 속성만 교체해야 하는 경우가 자주 발생합니다. 이번 글에서는 그 대표적인 예로, 두 배열에서 id가 일치하는 객체를 찾아 첫 번째 배열 객체의 name 속성을 두 번째 배열의 값으로 교체하는 방법을 알아보겠습니다.
먼저 다음과 같이 두 개의 객체 배열이 있다고 가정해 보겠습니다.
const arr1 = [
{ id: '124', name: 'qqq' },
{ id: '589', name: 'www' },
{ id: '45', name: 'eee' },
{ id: '567', name: 'rrr' }
];
const arr2 = [
{ id: '124', name: 'ttt' },
{ id: '45', name: 'yyy' }
];
요구 사항은 다음과 같습니다.
- 첫 번째 배열(arr1)을 순회하면서 두 번째 배열(arr2)에 동일한 id를 가진 객체가 있는지 찾습니다.
- 일치하는 객체가 있다면, arr1 해당 객체의 name 속성을 arr2 객체의 name 값으로 교체합니다.
- 일치하는 객체가 없다면 원본 객체를 그대로 유지합니다.
따라서 위 배열에 함수를 적용하면 최종 결과는 다음과 같아야 합니다.
const output = [
{ id: '124', name: 'ttt' },
{ id: '589', name: 'www' },
{ id: '45', name: 'yyy' },
{ id: '567', name: 'rrr' }
];
구현 방법: findIndex() 활용
배열 내장 메서드인 findIndex()를 사용하면 간결하게 구현할 수 있습니다. arr1의 각 요소에 대해 arr2 안에서 같은 id를 가진 요소의 인덱스를 찾고, 존재할 경우 name 값을 덮어쓰는 방식입니다.
const arr1 = [
{ id: '124', name: 'qqq' },
{ id: '589', name: 'www' },
{ id: '45', name: 'eee' },
{ id: '567', name: 'rrr' }
];
const arr2 = [
{ id: '124', name: 'ttt' },
{ id: '45', name: 'yyy' }
];
const replaceByOther = (arr1, arr2) => {
for (let i = 0; i < arr1.length; i++) {
const el = arr1[i];
// arr2에서 동일한 id를 가진 객체의 인덱스를 검색
const index = arr2.findIndex(elm => el['id'] === elm['id']);
if (index === -1) {
continue; // 일치하는 항목이 없으면 건너뜀
}
el['name'] = arr2[index]['name']; // name 속성 교체
}
};
replaceByOther(arr1, arr2);
console.log(arr1);
코드 설명
for루프로 arr1의 모든 객체를 하나씩 확인합니다.findIndex()는 조건을 만족하는 첫 번째 요소의 인덱스를 반환하며, 조건에 맞는 요소가 없으면-1을 반환합니다.index === -1인 경우에는continue로 다음 요소로 넘어갑니다.- 일치하는 항목을 찾았다면
el['name']에 arr2 객체의 name 값을 할당해 교체합니다.
실행 결과
콘솔 출력 결과는 다음과 같습니다.
[
{ id: '124', name: 'ttt' },
{ id: '589', name: 'www' },
{ id: '45', name: 'yyy' },
{ id: '567', name: 'rrr' }
]
arr2에 존재했던 id('124', '45')를 가진 객체들의 name이 각각 'ttt', 'yyy'로 교체되었고, 나머지 객체는 원래 값 그대로 유지된 것을 확인할 수 있습니다.
성능 개선: Map 활용하기
위 방식은 이해하기 쉽지만, 매 요소마다 arr2 전체를 탐색하므로 시간 복잡도가 O(n×m)입니다. 따라서 배열의 크기가 커지면 성능이 저하될 수 있습니다. 데이터 양이 많다면 arr2를 Map으로 변환해 조회 시간을 O(1)로 줄이는 것이 좋습니다.
const replaceByOther = (arr1, arr2) => {
const map = new Map(arr2.map(obj => [obj.id, obj.name]));
arr1.forEach(el => {
if (map.has(el.id)) {
el.name = map.get(el.id);
}
});
};
이처럼 Map을 활용하면 대용량 데이터에서도 훨씬 빠르게 처리할 수 있습니다.
마무리
이번 글에서는 두 객체 배열을 id 기준으로 비교하여 특정 속성을 교체하는 방법을 살펴보았습니다. findIndex()를 이용한 직관적인 방법과 Map을 활용한 성능 최적화 방법 모두 실무에서 자주 사용되는 패턴이니, 데이터 크기와 상황에 맞게 선택하여 활용해 보시기 바랍니다.