깊은 복사(deep copy) (TIL 19일차)

EenSung Kim·2021년 4월 23일
0

"원래 다루려고 했던 주제는 아니지만.."


Javascript는 원시 자료형(primitive)과 객체 자료형(object)을 구분하고 있는데요. 원시 자료형은 값 그 자체를 복사해 전달하지만, 객체 자료형은 자료형을 가리키는 주소를 복사해 전달합니다.

let a = { b: 'c', d: 'e' };
let b = a;

console.log(a === b);  // true
b.f = 'g';
console.log(a); // {b: 'c', d: 'e', f: 'g'}

따라서 b = a 와 같은 방식으로 객체를 복사하면, 사실은 객체 그 자체가 복사되는 것이 아니라 객체를 가리키는 주소가 복사됩니다. a === b 가 성립하는 것도 가리키는 주소가 같기 때문이죠.

이런 방법은 b를 이용해 새로운 객체 속성을 추가할 때, a 도 같이 변하는 문제가 있습니다. 전혀 다른 곳에서 자료를 수정할 수 있는 위험성이 있죠. 실제로 b.f = 'g'; 라는 구문을 추가하면 b 는 물론이고, a 객체를 확인해도 f: 'g' 라는 새로운 속성이 추가된 것을 알 수 있습니다.

이를 해결하는 방법이 깊은 복사(deep copy)입니다. 주소를 복사하는 것이 아닌 새로운 객체를 만들어 전달하는 방법이죠. deep copy 에 여러가지 방법이 있지만 spread 문법으로 아주 간단하게 사용할 수 있습니다.

let a = { b: 'c', d: 'e' };
let b = { ...a };

console.log(b);  // { b: 'c', d: 'e' }
console.log(a === b);  // false
b.f = 'g';
console.log(a);  // { b: 'c', d: 'e' }
consolg.log(b);  // {b: 'c', d: 'e', f: 'g'}

spread 문법은 ...을 이용해 객체 내부의 속성을 풀어서 전개합니다. 그래서 {} 로 감싸주고 사용하게 되면 새로운 객체에 a 내부의 속성을 복사하게 되죠. 이 때 b 는 주소를 전달받은 것이 아닌 전혀 새로운 객체이기 때문에 a === b 는 false 가 됩니다.

또한 b.f = 'g'; 라는 구문을 추가해도 a 는 전혀 변화하지 않고 원래 모양을 유지하죠. 깊은 복사는 이처럼 a 객체의 속성을 b 로 복사해도 a 와 b 가 상호간의 영향을 미치지 않는 상태를 만들어주는 복사입니다.


객체 자료형의 복사는 사실 매우 중요하고 또 복잡하면서도 쉽지 않은 개념이라고 합니다. 위에서 언급한 spread 문법도 사실 개념적으로 완벽한 deep copy를 해주지는 않는다고 해요. 그래서 본격적인 공부와 블로깅은 내일 이어가보려고 합니다.

profile
iOS 개발자로 전직하기 위해 공부 중입니다.

0개의 댓글