Front-End/JavaScript

[JavaScript] 깊은 복사, 얕은 복사

김당 2023. 3. 2. 00:15

JavaScript의 데이터 타입에는 2가지가 존재하며 타입에 따라 복사 방식이 다르다.

  • 원시타입 : Number, String, Boolean, Undefined, Null 등
  • 참조타입 : Object, Array 등

 

1. 깊은 복사 (Deep Copy)

: 독립적인 메모리에 객체의 실제 값만을 복사하여 생성하는 것

: 원시타입의 변수를 복사할 때는 복사된 값을 독립적인 다른 메모리에 할당하기 때문에 원래 값과 복사된 값이 서로 영향을 미치지 않는다.

: 깊은 복사된 객체는 객체 안에 객체가 있을 경우에도 원본과의 참조가 완전히 끊어진 객체를 말한다.

const a = 1;
let b = a;

b = 2

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

 

 

 

복사 방법

JSON.stringify() : 객체를 인수로 받아 받은 객체를 문자열로 치환, 이때 원본 객체와의 참조가 모두 끊어진다.
JSON.parse() : 치환된 문자열을 다시 객체로 치환
*이 방법이 가장 간단하고 쉽지만 다른 방법에 비해 느리고, 객체가 function일 경우에는 undefined로 처리한다는 것이 단점이다.
const obj = {
  a: 1,
  b: { c: 2 },
  func: function() {
    return this.a;
  }
};

const copyObj = JSON.parse(JSON.stringify(obj));

copyObj.b.c = 3;

console.log(obj); // { a: 1, b: { c: 2 }, func: function(){ return this.a; } }
console.log(copyObj); // { a: 1, b: { c: 3 } }

console.log(copyObj.func); //undefined
console.log(obj.b.c === copyObj.b.c); //false

 

 

2. 얕은 복사 (Shallow Copy)

: 객체의 참조값을 복사하는 것으로 기존 값과 복사된 값이 같은 참조를 가리키고 있는 것

: 참조타입의 변수를 복사할 때는 저장된 메모리의 주소를 복사하기 때문에 서로 영향을 미친다.

const a = {
  one: 1,
  two: 2,
};

let b = a;
 
b.one = 3;
 
console.log(a); // { one: 3, two: 2 }
console.log(b); // { one: 3, two: 2 }

 

 

복사 방법

Object.assign(생성할 객체, 복사할 객체);
: 객체 자체는 깊은 복사가 수행되지만 2차원 이상의 객체는 얕은 복사가 수행된다.

 

: 아래 예제에서는 1차원 객체인 obj를 깊은 복사하였기 때문에 copyObj라는 복사 객체를 생성 후 값을 변경해도 기존 obj의 값이 바뀌지 않고 서로 참조값이 다른 것을 확인할 수 있다.

const obj = { a: 1 };
const copyObj = Object.assign({}, obj);

copyObj.a = 2;

console.log(obj); // { a: 1 }
console.log(obj === copyObj); // false

 

: 아래 예제에서 복사된 객체 자체와 기존 객체 자체는 서로 다른 객체지만, 그 안에 들어가 있는 객체는 얕은 복사가 되어 기존 객체와 같은 참조값을 가리키고 있기 때문에 같은 참조값을 가리키는 것을 확인할 수 있다.

const obj = {
  a: 1,
  b: {
   c: 2
  }
}

const copyObj = Object.assign({}, obj);

copyObj.a = 2;
copyObj.b.c = 3;

console.log(obj); // { a: 1, b: { c: 3 } }
console.log(copyObj); //{ a: 2, b: { c: 3 } }
console.log(obj.a === copyObj.a); //false
console.log(obj.b.c === copyObj.b.c); // true

 

전개연산자(Spread Operator)
: 전개연산자도 마찬가지로 복사한 객체 자체는 깊은 복사이지만 내부 객체(2차원 객체)는 얕은 복사가 된다.
const obj = {
  a: 1,
  b: { c: 2 },
};

const copyObj = {...obj};

copyObj.b.c = 3;

console.log(obj); // { a: 1, b: { c: 3 } }
console.log(obj.b.c === copyObj.b.c); // true

 

 

 

참고

: https://bbangson.tistory.com/78

: https://dori-coding.tistory.com/entry/JavaScript-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%ACShallow-Copy%EC%99%80-%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%ACDeep-Copy