하얀 코딩

[JavaScript - 14] 얕은 복사(shallow copy)와 깊은 복사(deep copy) 본문

JavaScript

[JavaScript - 14] 얕은 복사(shallow copy)와 깊은 복사(deep copy)

whitecoding 2022. 11. 18. 15:06

특징

얕은 복사 : 실제값 복사 (Number, String, Boolean, Null, Undefined)

깊은 복사 : 주소값 복사 (Object, Symbol) 등

 

원시값은 기본 자료형(단순한 데이터)을 의미합니다.  Number, String, Boolean, Null, Undefined 등이 해당합니다. 

변수에 원시값을 저장하면 변수의 메모리 공간에 실제 데이터 값이 저장됩니다. 

할당된 변수를 조작하려고 하면 저장된 실제 값이 조작됩니다.

 

참조값은 여러 자료형으로 구성되는 메모리에 저장된 객체입니다. Object, Symbol 등이 해당합니다.

변수에 객체를 저장하면 독립적인 메모리 공간에 값을 저장하고, 변수에 저장된 메모리 공간의 참조(위치 값)를 저장하게 됩니다.

그래서 할당된 변수를 조작하는 것은 사실 객체 자체를 조작하는 것이 아닌, 해당 객체의 참조를 조작하는 것입니다. 

 

※ 원시/참조 자료에 대한 내용

https://white120.tistory.com/18

 

[JavaScript - 8] 원시 / 참조 자료형

원시 자료형(primitive data types) 1. 객체가 아니면서 method를 가지지 않는다. 2. 원시 자료형은 데이터 보관함에 저장할 때 하나의 데이터만 담을 수 있다. 3. string, number, boolean, undefined, null, symbol, bigin

white120.tistory.com

얕은 복사(shallow copy)

const test1 = {
  one: 1,
  two: 2,
};
let test2 = test1;
 
test2.one = 3;
 
console.log(test1); // { one: 3, two: 2 } 출력
console.log(test2); // { one: 3, two: 2 } 출력
 
// 기존 값에 영향을 끼친다.
// 이처럼 객체의 참조값(주소값)을 복사하는 것을 얕은 복사라고 한다.

깊은 복사(deep copy)

const test1 = 1;
let test2 = test1;
 
test2 = 2;
 
console.log(test1); // '1';
console.log(test2); // '2';
 
// 기존 값에 영향을 끼치지 않는다.
// 이것은 자료형을 깊은 복사한 것이다.

1. Spread 연산자

const obj1 = { a:1, b:2 };
const obj2 = { ...obj };

obj2.a = 100;

console.log( obj1 === obj2 ) // false
console.log( obj1.a ) // 1

// obj1과 obj2는 다른 주소를 갖게되었다. (그러나 딱, 1 depth 까지만)

2. Object.assign()

const obj1 = { a:1, b:2 };
const obj2 = Object.assign({}, obj1);

obj2.a = 100;

console.log( obj1 === obj2 ) // false
console.log( obj1.a ) // 1

// obj1과 obj2는 다른 주소를 갖게되었다. (그러나 딱, 1 depth 까지만)

3. spread 연산자를 이용해 depth 2까지 복사를 할 수는 있다. (당연 Object.assign()도 가능하다.)

const obj1 = { a: { b:1, c:1 }, d: 2};
const obj2 = { ...obj1, a:{ ...obj1.a } };

obj1.a.b = 100;

console.log(obj1 === obj2) // false
console.log(obj2.a.b) // 1

//1 depth으로 쓰는 용도로 2 depth 이상의 Deep copy로 만드는건 원하는 결과가 나오지 않을 확률이 높으니 주의할 것.

정리

Object.assign() 메소드도 spread 연산자 둘 다 완벽한 Deep copy 되지 않는다.

1. 객체가 서로 다르다고 깊은 복사가 이루어진건 아니다.
2. 1 depth 까지는 확실하게 Deep copy 가능하다.
3. 2 depth 이상이면 Shallow copy. (위 3번을 통해 Deep copy로 해결은 가능하다.)

4. 1 depth으로 쓰는 용도로 2 depth 이상의 억지로 Deep copy로 만드는건 원하는 결과가 나오지 않을 확률이 높으니 주의할 것.

 

완벽한 Deep copy를 위한 다른 방법

1. 재귀적으로 깊은 복사를 수행
2. Lodash의 cloneDeep 함수 사용
3. JSON.parse()와 JSON.stringify()함수 사용