[JavaScript] 깊은 복사, 얕은 복사, 스프레드 연산자(spread operator)

jjee·2025년 8월 19일

JavaScript

목록 보기
7/12

썸네일

깊은 복사, 얕은 복사, 스프레드 연산자(spread operator)

깊은 복사와 얕은 복사, 그리고 스프레드 연산자에 대해 알아보자.

깊은 복사(Deep Copy)

깊은 복사란 실제 값을 복사하는 것으로, 원본과 복사본은 각각의 독립된 값이 된다.
주로 Primitive 타입과 같은 원시값은 깊은 복사가 이루어진다.

let a = 2;
let b = a;
console.log(a); // 2
console.log(b); // 2

b = 5;
console.log(a); // 2
console.log(b); // 5
// b의 값만 변한 것 확인 가능

원시값은 값을 복사 할 때 복사된 값을 다른 메모리에 할당 하기 때문에 원래의 값과 복사된 값이 서로에게 영향을 미치지 않는다.

복사 방법

  1. JSON.parse && JSON.stringify
    JSON.parse(JSON.stringify())

    원본 객체의 값을 강제로 문자열로 변환 후 다시 객체로 만드는 과정을 거쳐 기존의 원본 객체와의 참조를 끊어내는 방식이다.

    const a = { name: "apple", obj: { one: 1, two: 2 }, arr: [1, 2] };
    const c = JSON.parse(JSON.stringify(a));
    c.name = "eliie";
    c.obj.one = 3;
    c.arr.push(3);
    
    console.log(c);
    console.log(a.name === c.name); //false
    console.log(a.obj.one === c.obj.one); //false => object 타입은 같은 ref참조값이므로 변경 시 같이 변경됨
    console.log(a.arr === c.arr); //false => object 타입은 같은 ref참조값이므로 변경 시 같이 변경됨

    가장 간단한 방법이라고 할 수 있지만, 다른 방법들에 비해 오래 걸린다는 단점이 있다.
    또한, 함수(Function)나 심볼(Symbol)인 경우 null이나 undefined로 처리하고, 일부 데이터가 누락되거나 타입이 변경되는 등의 문제가 있다.

    순수 데이터 객체(plain data object)를 복사할 때만 안전하게 사용이 가능하다.

  2. Lodash 라이브러리
    라이브러리를 사용하면 더 쉽고 안전하게 깊은 복사를 할 수 있다.

    const deepCopy = require("lodash.clonedeep")
    const copy = deepCopy(object);

    사용하기 위해서는 설치를 해야한다.

  3. 반복문으로 하나하나 복사, 재귀 함수
    반복문을 이용하여 값을 일일이 복사할 수 있다.
    함수를 만들어서 모든 뎁스를 깊은 복사 하도록 코드를 짤 수 있다.

    직접 작업해야 하는 만큼 손이 많이 가고 복잡하여 번거로운 방법이다.

  4. structuredClone()
    structuredClone(value)

    자바스크립트에서 structuredClone()이라는 깊은 복사 기능이 추가 되어 번거로운 작업 없이도 깊은 복사가 가능해졌다.

    mdn structuredClone()

얕은 복사(shllow Copy)

얕은 복사란 객체의 참조값을 그래도 복사하는 것으로, 원본과 복사본이 동일한 참조값(주소값)을 가져 실제 값을 공유하게 된다.
주로 객체(Object)와 같은 값은 얕은 복사가 이루어진다.

const team1 = { name: "hello" };
const team2 = team1;

team2.name = "world";

console.log(team1.name); //world
console.log(team2.name); //world
console.log(team1.name === team2.name); //true

얕은 복사는 참조값을 복사하게 되기 때문에 얕은 복사한 값을 수정하면 같은 참조값을 가지는 원본 객체의 값까지 변경된다.

얕은 복사란, 객체를 복사할 때 기존 값과 복사된 값이 같은 참조를 가리키고 있는 것을 말한다.
객체 안에 객체를 가진 값을 복사했을 때 한개의 객체라도 기존의 변수 객체를 참조하고 있다면 이는 얕은 복사라고 한다.

복사 방법

  1. 배열의 복사 메소드
    Array.slice(), Array.concat(), Array.from()

    기존 배열에서 추출하여 새로운 배열을 리턴하는 메소드가 있다.
    이 메소드는 1차원 배열이나 객체까지는 깊은 복사가 허용되나, 2차원 이상 부터는 얕은 복사하여 원본 객체의 참조값을 복사한다.

  2. Object.assign()
    Object.assign(생성할 객체, 복사할 객체)

    메소드의 첫 번째 인자로 빈 객체를 넣어주고 두 번째 인자로 복사할 객체를 넣어준다.

    let user = {
      name: "홍길동",
      age: 32
    };
    
    let clone = Object.assign({}, user);

    복사된 객체(clone) 자체는 기존 object와 다른 새 객체이다.
    하지만 그 안에 들어가 있는 값은 기존 object안의 값과 같은 참조 값을 가리키므로 얕은 복사라 할 수 있다.

Spread 연산자(...)

위의 내용을 정리하면 Spread 연산자 역시 얕은 복사 방법인 것을 알 수 있다.

...변수명

const team1 = {
  name: "홍길동",
  crew: { one: "강감찬", two: "윤동주" }
};
const team2 = { ...team1 };
team2.name = "김두환";
team2.crew.one = "이순신";

console.log(team1.name === team2.name); //false 
console.log(team1.crew.one === team2.crew.one); //true

스프레드 연산자를 이용하여 복사를 시도하면 1뎁스의 값은 그대로 복사가 된다.
하지만 2뎁스 이상의 경우 참조값을 복사하게 되기 때문에 얕은 복사라 할 수 있다.

참고

profile
내가 나에게 알려주는 개발 공부

0개의 댓글