JavaScript에서 객체나 배열을 복사할 때 단순히 =을 쓰면 참조만 복사된다.
이때 필요한 것이 바로 얕은 복사(shallow copy) 와 깊은 복사(deep copy)이다.
얕은 복사와 깊은 복사의 차이점과 JS에서 안전하게 복사하는 방법을 알아보자.
📍 얕은 복사(Shallow Copy)란?
- 1단계만 복사하고, 그 안의 객체나 배열은 참조를 유지하는 방식이다.
- 즉, 복사된 객체의 내부에 있는 객체는 원본과 여전히 같은 메모리 주소를 참조한다.
예시
const original = {
name: 'Alice',
address: {
city: 'Seoul'
}
};
const copy = { ...original };
copy.name = 'Bob';
copy.address.city = 'Busan';
console.log(original.name);
console.log(original.address.city);
copy.address.city를 바꾸면 original.address.city도 바뀝니다.
- 이는
address 객체가 얕게 복사되었기 때문입니다.
📍 깊은 복사(Deep Copy)란?
- 객체 내부의 모든 중첩 객체까지 재귀적으로 복사하는 방식이다.
- 복사된 객체는 원본과 완전히 독립적인 구조를 가진다.
예시
const original = {
name: 'Alice',
address: {
city: 'Seoul'
}
};
const deepCopy = structuredClone(original);
deepCopy.address.city = 'Busan';
console.log(original.address.city);
structuredClone은 깊은 복사를 수행하므로 원본이 유지된다.
⚠️ 주의할 점
1️⃣ JSON 방식은 다음과 같은 정보가 손실된다.
const obj = {
date: new Date(),
func: () => {},
undef: undefined
};
const copy = JSON.parse(JSON.stringify(obj));
console.log(copy);
- JSON 방식은 일부 데이터 타입을 정확히 복사하지 못한다.
- 함수,
undefined, 날짜(Date) 객체 등은 손실되거나 변형된다.
2️⃣ structuredClone()은 다음 환경에서만 지원
- Chrome 98+, Firefox 94+, Node.js 17+ 등
- 구형 브라우저나 Babel 환경에서는 폴리필 필요
3️⃣ lodash.cloneDeep() 사용 시 용량 증가 유의
pnpm add lodash
import cloneDeep from 'lodash/cloneDeep';
const copied = cloneDeep(obj);
✅ 정리
📌 복사 방법 요약
| 방법 | 복사 타입 | 설명 |
|---|
{ ...obj }, Object.assign() | 얕은 복사 | 객체 1단계만 복사, 중첩 객체는 참조 유지 |
array.slice(), [...arr] | 얕은 복사 | 배열 요소를 복사하되 내부 객체는 참조 유지 |
JSON.parse(JSON.stringify(obj)) | 깊은 복사 (제한적) | 중첩 객체 복사 가능하지만 함수, undefined, Date 등은 손실됨 |
structuredClone(obj) | 깊은 복사 | 최신 브라우저/Node.js 지원, 대부분의 구조 안전하게 복사 가능 |
라이브러리 사용 (lodash.cloneDeep) | 깊은 복사 | 복잡한 객체도 안전하게 복사, 브라우저 호환성 ↑ |
📌 상황별 추천
| 상황 | 추천 방식 |
|---|
| 간단한 객체 복사 (중첩 없음) | { ...obj } |
| 중첩된 객체까지 완전한 복사 필요 | structuredClone() |
| 복잡한 구조, 구형 브라우저 호환성 고려 필요 | lodash.cloneDeep() |
| JSON 형태 전송/저장 전 객체 정제 용도 | JSON.stringify/parse |