Javascript

얕은복사(Shallow Copy) , 깊은 복사(Deep Copy)

trophy98 2024. 1. 21. 17:37

자바스크립트에서의 데이터 타입

자바스크립트에서는 기본적으로 두 가지 유형의 데이터 타입을 가지고 있습니다. 

원시 타입(Primitive types) 

원시 타입은 자바스크립트에서 가장 기본적인 데이터 타입입니다. 해당 타입에서 이들은 불변(immutable)하며, 메모리에 직접 저장되고 복사됩니다.

// 숫자(Number)
let num1 = 100;
let num2 = num1; // 값에 의한 복사

// num1을 변경해도 num2에 영향을 주지 않음
num1 = 200;
console.log(num1); // 200
console.log(num2); // 100 (변경되지 않음)

참조 타입(Reference Types)

참조 타입은 메모리 상의 객체를 가리키는 참조에 의해 변수에 저장되고 복사됩니다. 따라서 , 한변수를 다른 변수에 할당하면 객체의 참조가 복사됩니다. 이로 인해 두 변수가 동일한 객체를 가리키게 되어, 한 객체의 변경이 다른 객체에도 영향을 줄 수 있습니다.

// obj 객체
let obj = {
	a: 1,
    b: 2,
    c: 3
};

let newObj = obj;

newObj.a = 100; // a에 값 100을 재할당 합니다.

console.log(obj.a); // 100
console.log(newObj.a); // 100
// 두 객체는 동일한 주소를 참조하기 때문에 a값이 바뀌게 되고 반환하는 a의 값이 둘다 변경됩니다.

 

이처럼 원시 타입에는 숫자나 문자열, boolean, undefined,null, Symbol 과 같은 간단한 데이터입니다. 반면에 참조 타입은 객체(Object), 배열(Array), 함수(Function)와 같은 복잡한 데이터 구조를 가지고 있습니다.

 

얕은 복사와 깊은 복사의 필요성

원시 타입은 값에 의한 복사(Value Copy)를 통해 변수에 저장되고 복사됩니다. 이는 각 변수가 독립적인 값을 가지며, 하나를 변경해도 다른 하나에 영향을 주지 않습니다.

참조 타입은 메모리 상의 객체를 가리키는 참조에 의해 변수에 저장되고 복사됩니다. 따라서, 한 변수를 다른 변수에 할당하면 객체의 참조가 복사됩니다. 이로 인해 두 변수가 동일한 객체를 가리키게 되어, 한 객체의 변경이 다른 객체에도 영향을 줄 수 있습니다.

 

얕은 복사(Shallow Copy)

얕은 복사는 객체의 최상위 레벨만 복사합니다. 이는 중첩된 객체나 배열은 복사되지 않고, 원본과 복사본이 이 중첩된 객체에 대한 참조를 공유하는 것을 의미하고 있습니다.

// 얕은 복사 예시
let original = {
    a: 1,
    b: { c: 2, d: 3 }
};

// Object.assign을 사용한 얕은 복사
let shallowCopy = Object.assign({}, original);

// 원본 객체의 최상위 속성을 변경
original.a = 10;

// 원본 객체의 중첩된 객체를 변경
original.b.c = 20;

console.log("Original:", original); // { a: 10, b: { c: 20, d: 3 } }
console.log("Shallow Copy:", shallowCopy); // { a: 1, b: { c: 20, d: 3 } }

이 예시를 보면 original 객체의 a 속성을 변경했을 때 shallowCopy에 영향을 주지 않습니다. 하지만 b.c 속성을 변경하면 shallowCopy에서도 영향을 받습니다. 이는 b 가 중첩된 객체이기 때문입니다.

깊은 복사(Deep Copy)

깊은 복사는 객체의 모든 수준을 재귀적으로 복사하여 완전히 독립된 복사본을 만듭니다. 중첩된 객체나 배열도 새롭게 복사됩니다.

이러한 깊은 복사는 객체의 완전한 독립성을 보장하기 위해 주로 사용되고 있습니다. 이는 중첩된 구조를 가진 객체를 다룰 때 중요하며, 객체의 한 부분이 다른 부분에 영향을 주지 않도록 하기 위해 사용됩니다.

// 깊은 복사 예시
let original = {
    a: 1,
    b: { c: 2, d: 3 }
};

// JSON 방법을 사용한 깊은 복사
let deepCopy = JSON.parse(JSON.stringify(original));

// 원본 객체의 최상위 속성을 변경
original.a = 10;

// 원본 객체의 중첩된 객체를 변경
original.b.c = 20;

console.log("Original:", original); // { a: 10, b: { c: 20, d: 3 } }
console.log("Deep Copy:", deepCopy); // { a: 1, b: { c: 2, d: 3 } }

 

이 예시를 보면 original 객체의 어떤 부분을 변경해도 deepCopy 에서는 아무런 영향이 없습니다. 이는 깊은 복사가 객체의 모든 수준의 데이터를 복사하기 때문입니다.

 

하지만 위의 JSON.parse(JSON.stringify()) 를 사용한 깊은 복사는 편리하지만 함수나 undefined, Symbol, 순환 참조 등 에서 올바르게 복사되지 않기에 이점을 참고해서 코드를 작성해야합니다.