본문 바로가기

Develop/Web

JS 값 복사하기 (Deep Copy)

자바스크립트에서 객체를 복사하는 방법은 여러가지가 있다.

 

얕은 복사

얕은 복사는 동일 객체를 참조하도록 한다. 객체는 메모리에 하나만 존재하고, 이를 가리키는 포인터가 추가되는 것이다.

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

const obj2 = obj1;
obj2.a = 4;
obj2.b.c = 5;

console.log(obj1.a); // 4
console.log(obj1.b.c); // 5

따라서 원본, 복사본 구분 없이 어느 것을 수정하더라도 당연히 모든 것이 수정되는 셈이다.

 

깊은 복사

메모리 상에 객체를 하나 더 생성하는 것이다. 따라서 원본과 복사본이 구별되며, 하나를 수정해도 다른 하나는 당연히 그대로 보존된다.

깊은 복사는 흔히 JSON.parse(JSON.stringify())를 이용한다.

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


const obj2 = JSON.parse(JSON.stringify(obj1));
obj2.a = 4;
obj2.b.c = 5;

console.log(obj1.a); // 1
console.log(obj1.b.c); // 2

다만 순환 참조 등의 상황에서는 JSON.parse(JSON.stringify())를 이용한 깊은 복사가 까다로울 수 있다.

 

structuredClone()

이번에 새로 나온 structuredClone을 사용하여 객체를 깊은 복사할 수 있다.

이것은 기존의 여러 깊은 복사를 위한 방법보다 견고하고, 객체가 거대한 경우 비교적 더 빨리 복사가 가능하다.

하지만 복사하려는 객체가 에러나 돔 객체, 함수 등을 포함하는 경우 원하지 않는 결과를 낼 수도 있다.

이 방법이 지원하는 값의 타입은 여기를 참고하라.

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

const obj2 = structuredClone(obj1);
obj2.a = 4;
obj2.b.c = 5;

console.log(obj1.a); // 1
console.log(obj1.b.c); // 2

 

structuredClone은 객체의 각 값을 복사하지만, 일부 값은 복사 대신 이동시킬 수도 있다. 이것은 어떤 값을 복사해서 비동기적 유효성 검사를 하는 동안 원본의 무결성을 보장하기 위한 상황 등에 유용하다.

 

structuredClone은 글을 작성하는 현재(2021.12.18) 최신 파이어폭스와 노드17 등에서만 사용할 수 있다.

 

참조

https://web.dev/structured-clone/

 

Deep-copying in JavaScript using structuredClone

For the longest time, you had to resort to workarounds and libraries to create a deep copy of a JavaScript value. The Platform now ships with structuredClone(), a built-in function for deep-copying.

web.dev