Lodash에서 객체를 다룰 때 _.assign()(별칭 _.extend())와 _.merge()는 비슷해 보이지만 동작 방식에 중요한 차이가 있습니다.
얕은 복사 vs 깊은 병합
assign과 extend는 소스(source) 객체의 각 속성을 순회하며 그 값을 있는 그대로 대상(destination) 객체에 복사합니다. 만약 속성 값 자체가 객체라 하더라도 내부 속성까지 재귀적으로 탐색하지 않습니다. 이러한 방식을 얕은 복사(shallow copy)라고 부르며, 객체 전체가 소스로부터 통째로 대상에 덮어써지게 됩니다.
반면 merge는 소스 객체의 각 속성을 살펴보면서 해당 속성이 객체인지 먼저 검사합니다. 객체라면 재귀적으로 한 단계 더 들어가서, 소스 객체의 자식 속성들을 대상 객체의 기존 속성과 매핑하며 깊게 병합(deep merge)합니다.
예제 코드
let _ = require('lodash');
let destination = {
a: {
b: 1,
c: 2
},
};
let source = {
a: {
d: 2,
c: 3
},
};
console.log(_.merge(destination, source));
console.log(_.extend(destination, source));
실행 결과
위 코드를 실행하면 다음과 같은 출력을 확인할 수 있습니다.
{ a: { b: 1, c: 3, d: 2 } }
{ a: { d: 2, c: 3 } }
결과 분석
_.merge()는 중첩된 객체 a의 내부 속성까지 깊게 비교하여 b: 1은 유지하고, c: 3으로 갱신되며, 새로운 속성 d: 2까지 추가된 것을 볼 수 있습니다. 즉, 기존 값과 새 값을 하나로 합치는 방식입니다.
반면 _.extend()는 객체 a 전체를 소스의 값으로 통째로 덮어쓰기 때문에 b: 1이 사라지고 소스 객체의 속성만 남습니다. 이처럼 중첩 객체를 다룰 때는 두 메서드의 차이를 반드시 인지하고 상황에 맞게 선택하는 것이 중요합니다.