본문 바로가기
JAVA

[JS] 원시형,객체형의 복사(얕은복사, 깊은 복사)

by code:J 2023. 8. 9.
반응형
SMALL

얕은 복사 (Shallow Copy)란?

  • 얕은 복사는 객체나 배열의 복사본을 생성할 때, 원본 객체의 내용을 복사하는 것이 아니라 원본 객체의 참조(reference)만을 복사합니다. 
  • 이는 새로운 객체를 생성하지만 원본 객체의 중첩된 객체나 배열에는 동일한 참조가 유지되므로 내부 객체의 변경이 복사본에도 영향을 미칠 수 있습니다.

깊은 복사(Deep Copy)란?

  • 깊은 복사는 객체나 배열의 복사본을 생성할 때, 원본 객체의 모든 내용을 완전히 복사하여 새로운 객체를 생성합니다. 
  • 이는 원본 객체의 모든 중첩된 객체나 배열도 독립적으로 복사되므로, 복사본을 변경해도 원본에 영향을 주지 않습니다.

 

원시형(Primitice Types)의 얕은 복사 

원시형 데이터는 변수에 직접 값을 저장합니다.

따라서 다른 변수에 할당할 때, 값이 복사되어 전달됩니다.

let originalValue = 42;
let copiedValue = originalValue; // 얕은 복사

copiedValue = 55;

console.log(originalValue); // 원본 값: 42
console.log(copiedValue);   // 복사된 값: 55

위의 예제에서 볼 수 있듯이, 원시형 데이터는 값 자체가 복사되기 때문에 하나의 변수를 수정해도 다른 변수에 영향을 미치지 않습니다.

 

객체형(Object Types)의 얕은 복사

객체는 참조(reference)로 저장됩니다.

객체를 다른 변수에 할당할 때, 참조 값만 복사되고 객체의 내용은 공유됩니다.

자바스크립트에서는 배열도 객체의 일종입니다.

let originalArray = [1, 2, 3];
let copiedArray = originalArray; // 배열의 얕은 복사

copiedArray.push(4);

console.log(originalArray); // 원본 배열: [1, 2, 3, 4]
console.log(copiedArray);   // 복사된 배열: [1, 2, 3, 4]

하지만 객체는 참조로 복사되기 때문에 객체의 내용이 변경되면 모든 변수에 영향을 미칩니다.

따라서 원본 배열과 복사된 배열 모두 같은 메모리 공간을 참조하게 됩니다. 

따라서 copiedArray를 변경한다면 originalArray에도 영향을 미치게 됩니다.

 

정확한 얕은 복사를 수행하려면 slice() 메서드나 전개연산자(...)를 사용해야 합니다.

slice() 메서드를 사용한 얕은 복사

let originalArray = [1, 2, 3];
let copiedArray = originalArray.slice(); // 얕은 복사

copiedArray.push(4);

console.log(originalArray); // 원본 배열: [1, 2, 3]
console.log(copiedArray);   // 복사된 배열: [1, 2, 3, 4]

 

전개 연산자 (...)를 사용한 얕은 복사

let originalArray = [1, 2, 3];
let copiedArray = [...originalArray]; // 얕은 복사

copiedArray.push(4);

console.log(originalArray); // 원본 배열: [1, 2, 3]
console.log(copiedArray);   // 복사된 배열: [1, 2, 3, 4]

 

이와 같이 slice() 메서드나 전개 연산자를 활용하면 배열은 얕은 복사를 하므로 새로운 배열을 생성할 수 있습니다.

 

 

배열의 요소가 객체일 때, 얕은 복사와 깊은 복사의 차이에 따라 복사된 배열에서 한 객체의 프로퍼티를 변경하면?

얕은 복사는 객체의 참조만을 복사하기 때문에, 복사된 배열과 원본 배열은 같은 객체를 참조하게 됩니다. 

따라서, 복사된 배열에서 객체의 프로퍼티를 변경하면 원본 배열에서도 해당 변경이 반영됩니다.

얕은 복사에서의 객체 프로퍼티 변경
let originalArray = [{ value: 1 }, { value: 2 }];
let shallowCopy = originalArray.slice(); // 얕은 복사

shallowCopy[0].value = 99;

console.log(originalArray); // [{ value: 99 }, { value: 2 }]
console.log(shallowCopy);   // [{ value: 99 }, { value: 2 }]

 

깊은 복사에서의 객체 프로퍼티 변경
function deepCopy(obj) {
    if (typeof obj !== 'object' || obj === null) {
        return obj;
    }

    let copy;
    if (obj instanceof Array) {
        copy = [];
        for (let i = 0; i < obj.length; i++) {
            copy[i] = deepCopy(obj[i]);
        }
    } else {
        copy = {};
        for (let key in obj) {
            if (obj.hasOwnProperty(key)) {
                copy[key] = deepCopy(obj[key]);
            }
        }
    }
    return copy;
}

let originalArray = [{ value: 1 }, { value: 2 }];
let deepCopiedArray = deepCopy(originalArray); // 깊은 복사

deepCopiedArray[0].value = 99;

console.log(originalArray); // [{ value: 1 }, { value: 2 }]
console.log(deepCopiedArray);   // [{ value: 99 }, { value: 2 }]

결론적으로, 얕은 복사는 객체의 참조를 공유하기 때문에 복사된 배열에서 객체의 프로퍼티를 변경하면 원본 배열에도 변경이 반영되며,

깊은 복사는 모든 내용을 복사하여 독립적인 객체를 생성하므로 복사된 배열에서 객체의 프로퍼티를 변경하더라도 원본 배열에는 영향을 주지 않습니다.

반응형
LIST