2 minute read

얕은 복사와 깊은 복사가 무엇인지 알아보자.

얕은 복사 (Shallow Copy)

참조(주소)값의 복사.

해당 데이터의 주소값을 전달하여 하나의 데이터를 공유한다.

객체의 얕은 복사

let obj = { value: 1};
let obj2 = obj;

obj2.value = 2;

console.log(obj.value) // 2
console.log(obj2.value) // 2
console.log(obj.value === obj2.value) // true

배열의 얕은 복사

let arr = [1, 2, 3];
let arr2 = arr;

arr2.push(4);

console.log(arr) // [1, 2, 3, 4]
console.log(arr2) // [1, 2, 3, 4]
console.log(arr === arr2) // true

깊은 복사 (Deep Copy)

값 자체의 복사.

아래 코드처럼 원시 자료형은 깊은 복사가 된다.

독립적인 메모리에 값 자체를 할당하고 생성하는 것이다.

let a = 1;
let b = a;

b = 2;

console.log(a); // 1;
console.log(b); // 2;
console.log(a === b); // false

그렇다면 참조 자료형인 객체의 값을 바꾸지 않고 (immutable) 활용하는 방법은 무엇이 있을까?

참조 자료형의 깊은 복사

  1. 객체 메소드 Object.assign() 을 이용하는 방법,

객체 메소드인 Object.assign()의 첫번쨰 인자로 빈 객체 {} 를 넣어주고,

다음 인자로 활용할 객체를 넣어준다.

배열 메소드 concat() 을 이용해 배열의 깊은 복사를 이루어낸다.

객체의 깊은 복사

let obj = { value: 1};
let obj2 = Object.assign({}, obj);

obj2.value = 2;

console.log(obj.value) // 1
console.log(obj2.value) // 2
console.log(obj.value === obj2.value) // false

------------------------------------------------

배열의 깊은 복사

let arr = [1, 2, 3];
let arr2 = [].concat(arr);

arr2.push(4);

console.log(arr) // [1, 2, 3]
console.log(arr2) // [1, 2, 3, 4]
console.log(arr === arr2) // false

위와 같이 객체에서 Object.assign() 메소드를 이용하면, 기존 obj의 값이 변하지 않는 깊은 복사가 이루어지고, 배열에서 concat() 메소드를 이용하면 기존 arr의 값이 변하지 않는 깊은 복사가 이루어진다.

  1. 전개 연산자 (Spread Operator)를 이용하는 방법.
객체의 깊은 복사

let obj = { value: 1};
let obj2 = {...obj};

obj2.value = 2;

console.log(obj.value) // 1
console.log(obj2.value) // 2
console.log(obj.value === obj2.value) // false

------------------------------------------------

배열의 깊은 복사

let arr = [1, 2, 3];
let arr2 = [...arr];

arr2.push(4);

console.log(arr) // [1, 2, 3]
****console.log(arr2) // [1, 2, 3, 4]
console.log(arr === arr2) // false

위와 같이 깊은 복사를 이루어낼 수 있지만,

객체의 경우 2차원 객체의 깊은 복사는 이루어지지 않는다.

let obj = { a: 1, b: { c: 2 } };
let obj2 = Object.assign({}, obj);

obj.b.c = 3;

console.log(obj.b.c); // 3
console.log(obj2.b.c); // 3
console.log(obj.b.c === obj2.b.c); // true

이 문제는 전개 연사자 역시 마찬가지이다.

let obj = { a: 1, b: { c: 2 } };
let obj2 = { ...obj };

obj.b.c = 3;

console.log(obj.b.c); // 3
console.log(obj2.b.c); // 3
console.log(obj.b.c === obj2.b.c); // true

그렇다면 2차원 객체의 깊은 복사는 어떻게 행해야할까?

JSON 메소드를 이용한 2차원 객체의 깊은 복사

let obj = { a: 1, b: { c: 2 } };
let obj2 = JSON.parse(JSON.stringfy(obj));

obj2.b.c = 3;

console.log(obj.b.c); // 2
console.log(obj2.b.c); // 3
console.log(obj.b.c === obj2.b.c); // false

하지만, JSON 메소드를 사용하는 것 역시 문제점이 있는데,

다른 방법들에 비해 속도가 느리다는 성능적인 문제와,

JSON.stringify() 메소드는 함수를 만났을 때 undefined를 반환하기 때문에 범용성이

떨어진다는 점이다.

더 효율적인 객체의 깊은 복사는 앞으로 공부하며 더 알아보도록 하자!

Updated: