본문 바로가기
Frontend

얕은 복사(shallow copy) vs 깊은 복사(deep copy)

by 미래 감자 2025. 9. 8.

프로그래밍을 하다 보면 객체나 배열을 복사(copy) 해야 하는 경우가 자주 발생한다. 이때 중요한 개념이 바로 얕은 복사(Shallow Copy)깊은 복사(Deep Copy)이다.
두 가지 복사 방식이 실제 코드에서 어떤 차이를 만들어내는지 이해해야 의도치 않은 버그를 피할 수 있다.


💁🏻 적용 가이드

얕은 복사 먼저 고려하기
- 대부분의 UI 상태 변경은 얕은 복사로 충분하다.

깊은 복사는 신중하게
- 데이터 크기가 클수록 성능 부담이 커진다.

라이브러리 활용
- lodash.cloneDeep() 같은 유틸 라이브러리를 쓰면 안정적으로 깊은 복사를 구현할 수 있다.

 

✅  얇은 복사(Shallow Copy)

얕은 복사는 한 단계까지만 복사한다.
즉, 객체의 1차 속성은 새로운 메모리에 복사되지만, 그 안에 중첩된 객체나 배열은 원본의 참조를 공유한다.

 

[예시]

const user = {
  name: "Alice",
  address: {
    city: "Seoul",
    zip: "12345"
  }
};

// 얇은 복사 (Spread Operator 방법)
const shallowCopy = { ...user };

shallowCopy.name = "Bob";
shallowCopy.address.city = "Busan";

console.log(user.name); // "Alice" (독립적)
console.log(user.address.city); // "Busan" (원본까지 변경됨!)

name 같은 원시 값은 정상적으로 복사되지만, address 같은 객체는 참조를 공유하므로 원본까지 영향을 받는 것이다.

 

✅  깊은 복사(Deep Copy)

깊은 복사는 객체의 모든 단계까지 완전히 새로운 메모리에 복사한다.
따라서 원본과 복사본은 완전히 독립적이며, 한쪽의 변경이 다른 쪽에 영향을 주지 않는다.

 

[예시]

const user = {
  name: "Alice",
  address: {
    city: "Seoul",
    zip: "12345"
  }
};

// 깊은 복사 (JSON 방법)
const deepCopy = JSON.parse(JSON.stringify(user));

// 깊은 복사 (Lodash 라이브러리 방법)
import cloneDeep from 'lodash/cloneDeep';
const deepCopy = cloneDeep(user);

deepCopy.name = "Bob";
deepCopy.address.city = "Busan";

console.log(user.name); // "Alice"
console.log(user.address.city); // "Seoul"

 

이 경우 address 객체까지 완전히 새로운 값이 복사되었기 때문에 원본과 독립적으로 동작한다.

 

💡TIP

얕은 복사가 유리한 경우

  • 성능이 중요한 경우 (대량 데이터일 때 깊은 복사는 비용이 큼)
  • 원본과 복사본이 완전히 독립적일 필요가 없고, 부분만 복사하면 충분할 때
  • React, Vue 같은 프론트엔드 프레임워크에서 불변성(immutability)을 지키면서 얕은 수준의 상태 변경만 필요할 때

깊은 복사가 유리한 경우

  • 원본 데이터와 복사본이 완전히 독립적으로 동작해야 할 때
  • 상태 관리(store)에서 원본 데이터를 오염시키면 안 되는 경우
  • 서버에서 받은 응답(JSON) 데이터를 가공해서 새로운 데이터 구조를 만들 때

 


 

결론적으로, 얕은 복사는 가볍고 빠르지만 참조를 공유하기 때문에 주의가 필요하고, 깊은 복사는 안전하고 독립적이지만 비용이 크므로 실무에서는 대부분의 UI 상태 관리에는 얕은 복사로 충분하며, 원본 데이터와 복사본의 완전한 독립성이 필요한 경우에만 깊은 복사를 사용하는 것이 효율적이다.