자바스크립트에서 Number, String 같은 원시 타입(Primitive Type)은 값을 그대로 복사한다. 하지만 객체(Object)나 배열(Array) 같은 참조 타입(Reference Type)은 변수에 값이 아닌 메모리 주소(참조값)가 저장된다.
따라서 단순히 = 연산자로 복사하면 값 자체가 아닌 '주소'만 복사되어, 복사본을 수정할 때 원본도 함께 수정되는 불상사가 발생할 수 있다. 이를 방지하기 위해 얕은 복사와 깊은 복사를 사용한다.
얕은 복사는 객체의 가장 겉에 있는(1 depth) 속성들만 새로운 메모리에 복사하고, 내부에 중첩된 객체나 배열은 여전히 원본의 '메모리 주소'를 참조하는 복사 방식이다.
주로 스프레드 연산자(...)나 Object.assign()을 사용한다.
const original = {
name: "철수",
age: 25,
favorites: { food: "치킨" } // 내부 객체
};
// 얕은 복사 (스프레드 연산자 사용)
const shallowCopied = { ...original };
// 1. 겉에 있는 속성을 변경
shallowCopied.name = "영희";
console.log(original.name); // "철수" (원본 유지됨 ✅)
// 2. 내부에 중첩된 객체의 속성을 변경
shallowCopied.favorites.food = "피자";
console.log(original.favorites.food); // "피자" (원본도 같이 변경됨 ❌)
⚠️ 주의: 얕은 복사는 1단계 깊이까지만 안전하게 복사한다. 내부에 또 다른 객체나 배열이 있다면 원본 데이터가 훼손될 위험이 있다.
깊은 복사는 내부에 중첩된 객체나 배열까지 모두 완벽하게 새로운 메모리 공간에 복사하는 방식이다. 원본과 복사본은 완전히 독립적인 상태가 된다.
전통적으로 JSON.parse(JSON.stringify())를 많이 사용했으나, 최근에는 자바스크립트 내장 함수인 structuredClone()을 사용하는 것이 트렌드이다.
const original = {
name: "철수",
age: 25,
favorites: { food: "치킨" } // 내부 객체
};
// 깊은 복사 (structuredClone 사용 - Node.js 17+, 모던 브라우저 지원)
const deepCopied = structuredClone(original);
// 내부에 중첩된 객체의 속성을 변경
deepCopied.favorites.food = "피자";
// 원본 데이터 확인
console.log(original.favorites.food); // "치킨" (원본이 완벽히 보호됨 ✅)
console.log(deepCopied.favorites.food); // "피자"
💡 참고:
JSON.parse(JSON.stringify(original))방식은 함수(Functions)나undefined,Symbol등을 무시하는 단점이 있으므로, 최신 환경에서는structuredClone()사용을 권장한다. 환경이 여의치 않다면lodash라이브러리의_.cloneDeep()을 사용하는 것도 좋은 방법이다.
| 구분 | 설명 | 특징 | 주로 사용하는 방법 |
|---|---|---|---|
단순 할당 (=) | 메모리 주소만 복사 | 원본과 100% 연결됨 | - |
| 얕은 복사 | 1단계 깊이까지만 새로운 메모리에 복사 | 중첩된 객체는 원본과 연결됨 | ... (스프레드프레드 연산자), Object.assign() |
| 깊은 복사 | 중첩된 객체까지 모두 새로운 메모리에 복사 | 원본과 완벽히 분리됨 (안전) | structuredClone(), lodash.cloneDeep |
객체의 구조가 단순하다면 얕은 복사로 충분하지만, 복잡하게 중첩된 구조라면 데이터 오염을 막기 위해 반드시 깊은 복사를 사용해야 한다!