본문 바로가기
Category/JavaScript

... (Spread Operator)로 얕은 복사(Shallow Copy)하기

by Corinee 2025. 3. 18.
728x90
반응형

스프레드 연산자는 얕은 복사를 수행한다.

  • 하지만, 모든 값이 복사되는 방식이 다름!
  • Primitive 타입(원시값) → 새로운 값이 복사됨
  • Object 타입 (참조값) → 기존 객체의 참조(reference) 가 복사됨

코드 실행 결과

const test = {
  name: "bob",
  profile: {
    email: "test@",
  },
};

// 얕은 복사 (Shallow Copy)
const test2 = { ...test };

test2.name = "w"; // (1) 새로운 값으로 변경
test2.profile.email = "changed@"; // (2) 중첩 객체 내부 값 변경

console.log(test);  // 원본 객체
console.log(test2); // 복사된 객체

출력 결과

// 원본 객체 (test)
{
  "name": "bob",
  "profile": {
    "email": "changed@"
  }
}

// 복사된 객체 (test2)
{
  "name": "w",
  "profile": {
    "email": "changed@"
  }
}

왜 name은 따로 변경되고, email은 함께 변경될까?

(1) name = "bob" → Primitive 값 (원시 타입)

  • name은 문자열(Primitive Type) 이므로 새로운 값이 복사됨
  • 즉, test2.name을 변경해도 test.name에는 영향 없음

(2) profile = { email: "test@" } → Object (참조 타입)

  • profile은 객체(Object, Reference Type) 이므로,
  • ...test 사용 시, profile의 참조(reference) 가 복사됨
  • 즉, test.profile과 test2.profile은 같은 객체를 가리킴
  • 따라서 test2.profile.email을 변경하면 test.profile.email도 변경됨

해결 방법: 깊은 복사 (Deep Copy)

중첩 객체까지 복사하려면 structuredClone() 또는 JSON.parse(JSON.stringify()) 같은 깊은 복사 방법을 사용해야 한다.

(1) structuredClone() (최신 브라우저, Node.js 17+)

const test = {
  name: "bob",
  profile: {
    email: "test@",
  },
};

const test2 = structuredClone(test);
test2.profile.email = "changed@";

console.log(test); // 원본 유지됨
console.log(test2); // 변경됨

(2) JSON.parse(JSON.stringify()) (중첩 객체 복사)

const test = {
  name: "bob",
  profile: {
    email: "test@",
  },
};

const test2 = JSON.parse(JSON.stringify(test));
test2.profile.email = "changed@";

console.log(test); // 원본 유지됨
console.log(test2); // 변경됨

 

👉 결론:
Primitive 값은 새로운 값으로 복사되지만, Object는 참조만 복사되므로 같은 객체를 가리킴