자바스크립트에서 객체나 배열을 복사할 때 단순히 값이 복사되는 것이 아니라 참조가 복사되는 경우가 있다.
특히 객체와 배열 같은 참조 타입(Reference Type)에서는 복사의 방식에 따라 결과가 달라진다.
이때 등장하는 개념이 바로
**- Shallow Copy (얕은 복사)
이다.
먼저 JavaScript의 데이터 타입을 간단히 이해해야 한다.
JavaScript의 데이터는 크게 두 가지로 나뉜다.
| 구분 | 타입 |
|---|---|
| 원시 타입 | Number, String, Boolean, null, undefined, Symbol |
| 참조 타입 | Object, Array, Function |
원시 타입은 값 자체가 복사된다.
let a = 10;
let b = a;
b = 20;
console.log(a); // 10
하지만 객체나 배열은 메모리 주소가 복사된다.
const user1 = { name: "Kim" };
const user2 = user1;
user2.name = "Lee";
console.log(user1.name); // Lee
두 변수는 같은 객체를 가리키고 있기 때문이다.
이 문제를 해결하기 위해 객체를 복사하는 방법이 필요하다.
Shallow Copy는 객체의 최상위 수준만 복사하는 방식이다.
즉 새로운 객체가 만들어지지만
내부 객체는 동일한 참조를 공유한다.
예제로 살펴보자
const user = {
name: "Kim",
address: {
city: "Seoul"
}
};
const copyUser = { ...user };
copyUser.address.city = "Busan";
console.log(user.address.city); // Busan
spread operator를 사용하면 새로운 객체가 만들어지지만
address 객체는 같은 메모리를 참조한다.
그래서 내부 값을 변경하면 원본도 함께 변경된다.
Object.assign({}, obj)
const copy = { ...obj };
const copy = array.slice();
const copy = Array.from(array);
하지만 이러한 방식은 중첩 객체까지는 복사하지 않는다.
Deep Copy는 객체 내부의 모든 값까지 완전히 복사하는 방식이다.
즉 복사된 객체는 원본 객체와 완전히 독립적인 데이터가 된다.
const user = {
name: "Kim",
address: {
city: "Seoul"
}
};
const copyUser = structuredClone(user);
copyUser.address.city = "Busan";
console.log(user.address.city); // Seoul
이번에는 copyUser를 수정해도 원본 객체는 변경되지 않는다.
왜냐하면 내부 객체까지 완전히 새로운 메모리로 복사되었기 때문이다.
structuredClone
최근 JavaScript에서 제공하는 가장 안전한 방법이다.
const copy = structuredClone(obj);
예전에는 다음 방식이 많이 사용되었다.
const copy = JSON.parse(JSON.stringify(obj));
하지만 다음과 같은 단점이 있다.
함수 복사 불가능
undefined 값 제거
Date 객체 손실
JavaScript에서 객체를 복사할 때는 단순히 = 연산자를 사용하면 참조만 복사된다.
따라서 상황에 따라 다음과 같은 방법을 사용해야 한다.
단순 구조 → Shallow Copy
중첩 객체 존재 → Deep Copy
이 차이를 이해하는 것은 예상하지 못한 데이터 변경 버그를 방지하는 데 매우 중요하다.