자바스크립트의 객체와 관련된 depth, level, 혹은 depth level (파악한 바로는 세 용어가 혼재되어 사용되는 것 같습니다) 이라고 하는 용어가 있습니다. 객체는 내부에 또 다른 객체를 속성으로 지닐 수 있죠. 이렇게 객체 내부에 또 다른 객체가 중첩될 경우, 중첩된 객체의 depth 가 달라진다고 하는 개념입니다.
let a = {
b: 'c',
d: {
e: 'f',
},
g: {
h: {
i: 'j',
},
},
}
console.log(a.b); // c
console.log(a.d.e); // f
console.log(a.g.h.i); // j
위의 객체 a 에서 b, d, g 를 키로 갖는 속성들의 위치를 top level, 또는 depth level 1 이라고 할 수 있습니다. 마찬가지로 e, h 는 depth level 2 이고 i는 depth level 3 이 되겠죠.
객체의 depth 를 먼저 언급한 건 Shallow Copy(얕은 복사) 와 Deep Copy(깊은 복사) 가 이 depth 와 연관되어 있기 때문입니다. 깊은 복사가 객체 전체를 새롭게 복제한다면, 얕은 복사는 객체의 top level 에만 작용하기 때문에 객체가 중첩된 경우 전혀 다른 결과를 내놓게 됩니다.
지난 글에서 spread 문법을 활용하여 깊은 복사가 어떠한 것인지를 설명했었습니다만, 사실 spread 문법은 정확히는 얕은 복사입니다. top level 의 속성들 만을 복사해 가져오기 때문인데요. 예시를 통해 얕은 복사가 어떤 개념인지를 확인해보겠습니다.
let a = {
b: 'c',
d: {
e: 'f',
},
}
let copyA = {...a}; // copyA 에 a 를 얕은 복사
copyA.b = 'z';
copyA.d.e = 'y';
console.log(a.b); // c 일까 z 일까?
console.log(a.d.e); // f 일까 y 일까?
a 객체를 copyA 에 얕은 복사로 전달했습니다. spread 문법이 깊은 복사를 한다면 copyA 의 속성을 건드린다 해도 원본 a 객체에는 아무런 변화가 없어야 합니다. 실제로 copyA.b 를 'z' 라는 값으로 바꿔도 a.b 는 여전히 'c' 라는 값을 유지하죠.
문제는 depth level 2 의 위치에 있는 속성을 변경할 때 입니다. copyA.d.e 를 'y' 로 변경한다 해도 원본은 바뀌지 않을 거라는 예상과 달리, 원본의 a.d.e 또한 'y' 로 변경된 걸 확인할 수 있습니다.
이것이 바로 얕은 복사입니다. 객체의 속성을 변경해도 원본에 영향이 없도록 하고싶을 때 매우 간단히 사용할 수 있는 방법이지만, top level 의 속성만 복사되고 나머지는 원본과 연동되는 복사입니다.
그렇다면 깊은 복사는 어떻게 할 수 있을까요? 이 링크에서 깊은 복사에 대한 더 자세한 방법을 소개하고 있습니다. JSON 객체의 메소드를 이용하는 방법, 직접 재귀함수를 만들어 사용하는 것, 그리고 Lodash 라이브러리의 cloneDeep() 을 활용하는 방법, 이렇게 3가지 방법이 있네요. 활용할 일이 언제 올지는 모르겠습니다만 저라면 아마도 cloneDeep() 을 쓰게되지 않을까 싶네요.
참고한 자료
https://www.digitalocean.com/community/tutorials/copying-objects-in-javascript
https://medium.com/watcha/%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%AC%EC%99%80-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%AC%EC%97%90-%EB%8C%80%ED%95%9C-%EC%8B%AC%EB%8F%84%EC%9E%88%EB%8A%94-%EC%9D%B4%EC%95%BC%EA%B8%B0-2f7d797e008a
https://helloinyong.tistory.com/267