JavaScript의 얕은 복사(Shallow Copy) vs 깊은 복사(Deep Copy)

JavaScript는 데이터 타입에 따라 두 가지 방식으로 복사를 처리합니다.

원시 값 (값에 의한 복사)

원시 타입에는 string, number, boolean, symbol, bigInt, null이 포함됩니다. 원시 값을 복사하면 JavaScript는 메모리에 새로운 독립적인 버전을 생성합니다.

예시:

let a = 10;
let b = a;
b = 20;

결과: a는 10으로 유지됩니다.

비원시 값 (참조에 의한 복사)

객체와 배열은 다르게 동작합니다. 이들은 참조(reference)를 사용합니다. 객체를 복사할 때, 메모리 내 위치를 가리키는 포인터만 복사됩니다.

예시:

let original = { name: "YOO" };
let copy = original;
copy.name = "NEW";

결과: original.name은 이제 "NEW"가 됩니다.

차이점: 얕은 복사 vs 깊은 복사

**얕은 복사(Shallow copy)**는 객체의 최상위 레벨만 복사합니다. 만약 객체 내에 중첩된 객체가 있다면, 이는 여전히 원본의 중첩된 참조를 가리킵니다. **깊은 복사(Deep copy)**는 모든 값이 새로운 완전히 새로운 객체를 생성합니다.

피자로 비유해 보겠습니다:

  • 얕은 복사: 당신과 친구가 피자 한 판을 나눠 먹습니다. 친구가 한 조각을 먹으면, 당신이 먹을 피자도 줄어듭니다.
  • 깊은 복사: 당신과 친구가 각각 별도의 피자를 가지고 있습니다. 친구가 한 조각을 먹어도 당신의 피자는 그대로입니다.

얕은 복사 방법

스프레드 연산자(...)를 사용하여 얕은 복사를 할 수 있습니다.

let original = { name: "YOO", details: { age: 22 } };
let copy = { ...original };

경고: 만약 original.details.age를 변경하면, copy.details.age도 함께 변경됩니다. 이것이 얕은 복사의 함정입니다.

깊은 복사 방법

1. structuredClone()

현대적인 브라우저와 Node.js에서 제공하는 내장 함수입니다. 중첩된 구조를 완벽하게 처리합니다.

장점:

  • 빠르고 네이티브 방식입니다.
  • Date, RegExp, Map 등을 처리할 수 있습니다.

단점:

  • 객체에 함수나 DOM 노드가 포함되어 있으면 실패합니다.

2. JSON.parse(JSON.stringify())

객체를 문자열로 변환했다가 다시 객체로 되돌리는 오래된 방식입니다.

피해야 하는 이유:

  • undefined, Map, Set, Infinity와 같은 데이터를 잃어버립니다.
  • 특정 값을 손상시킬 수 있습니다.

Source: https://dev.to/yogesh_992/shallow-copy-vs-deep-copy-in-java-script-explained-in-easiest-way-3dg5