본문 바로가기
알쓸정보모음

[javascript] 깊은 복사, 얕은 복사에 대해서 !

by thecorative 2024. 11. 5.
반응형

 

 

1.깊은 복사란?(Deep copy)

 

  • 모든 계층의 데이터 복사:
    • 깊은 복사는 객체의 모든 중첩된 객체와 배열까지 복사하여, 복사된 객체가 원본 객체와 완전히 독립적으로 존재하도록 만듭니다.
    • 원본 객체와 복사된 객체가 같은 데이터를 포함하더라도, 중첩된 객체가 서로 다른 메모리 주소를 가지게 됩니다.
  • 원본 객체와의 독립성:
    • 깊은 복사된 객체를 수정해도 원본 객체에는 아무런 영향이 없습니다. 이는 얕은 복사와의 주요 차이점입니다.
    • 중첩된 객체나 배열의 값을 변경해도 원본 데이터에는 영향을 주지 않기 때문에, 독립적인 수정이 가능합니다.
  • 중첩된 객체나 배열에 적합:
    • 중첩된 구조 (e.g., 객체 안의 객체, 배열 안의 객체 등)를 가진 데이터를 복사해야 할 때 유용합니다.
    • 얕은 복사는 첫 번째 레벨의 값만 복사하므로 중첩된 데이터 구조에서는 깊은 복사가 필요할 수 있습니다.
  • 일반적인 복사 방식:
    • 깊은 복사는 보통 JSON.parse(JSON.stringify(obj))와 같이 JSON 방식을 이용하거나, structuredClone() (최신 브라우저에서 지원) 함수, 혹은 lodash의 cloneDeep() 같은 라이브러리를 사용해 구현합니다.
  • 성능에 미치는 영향:
    • 깊은 복사는 데이터의 모든 계층을 복사하기 때문에, 얕은 복사에 비해 상대적으로 더 많은 메모리와 시간이 소요될 수 있습니다. 특히 객체가 깊게 중첩될수록 성능에 영향을 미칩니다.

 

//예시 1
const userData = {
    name: "kim",
    age: 25,
    address: {
        city: "Seoul"
    }
};

const user2 = JSON.parse(JSON.stringify(userData));
user2.name = "Mr. Min";
user2.address.city = "Busan";

console.log(userData); // { name: "kim", age: 25, address: { city: "Seoul" } }
console.log(user2);    // { name: "Mr. Min", age: 25, address: { city: "Busan" } }

//예시 2
const original = { 
    name: "Alice", 
    details: { age: 25, address: { city: "Seoul" } }
};

const deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.name = "Bob";
deepCopy.details.address.city = "Busan";

console.log(original); // { name: "Alice", details: { age: 25, address: { city: "Seoul" } } }
console.log(deepCopy); // { name: "Bob", details: { age: 25, address: { city: "Busan" } } }

 

2.얕은 복사란?(Shallow copy)

 

  • 첫 번째 레벨의 프로퍼티만 복사:
    • 얕은 복사는 객체의 최상위 프로퍼티(첫 번째 레벨)의 값만 복사합니다. 객체 내부에 객체나 배열이 있는 경우, 그 내부 객체나 배열은 복사되지 않고 참조(레퍼런스)만 복사됩니다.
    • 즉, 중첩된 객체나 배열은 원본 객체와 동일한 메모리 주소를 공유하게 됩니다.
  • 원본 객체와의 상호 의존성:
    • 얕은 복사한 객체에서 최상위 프로퍼티를 수정하는 경우 원본 객체에 영향을 미치지 않지만, 중첩된 객체나 배열의 프로퍼티를 수정하면 원본 객체에도 영향을 줍니다.
    • 이는 얕은 복사가 원본 객체와 복사된 객체 사이에 상호 의존성을 가지는 주요 이유입니다.
  • 단순하고 빠른 복사 방식:
    • 얕은 복사는 원본 객체의 최상위 프로퍼티만 복사하므로, 깊은 복사에 비해 메모리와 시간이 덜 소요됩니다.
    • Object.assign(), Array.prototype.slice(), 그리고 스프레드 연산자(...) 등이 주로 얕은 복사에 사용됩니다.
  • 중첩된 구조에 적합하지 않음:
    • 얕은 복사는 중첩된 객체나 배열 구조를 독립적으로 다뤄야 할 때 적합하지 않습니다. 원본과의 상호 의존성을 초래할 수 있기 때문입니다.
    • 깊게 중첩된 객체나 복잡한 데이터 구조에서는 얕은 복사가 비효율적일 수 있습니다.
//예시1
const original = {
    name: "Alice",
    details: { age: 25, address: { city: "Seoul" } }
};

const shallowCopy = Object.assign({}, original);
shallowCopy.name = "Bob";
shallowCopy.details.address.city = "Busan";

console.log(original); // { name: "Alice", details: { age: 25, address: { city: "Busan" } } }
console.log(shallowCopy); // { name: "Bob", details: { age: 25, address: { city: "Busan" } } }


//예시2
const arr = [{ name: "Alice" }, { name: "Bob" }];
const shallowCopyArr = arr.slice();

shallowCopyArr[0].name = "Charlie";
console.log(arr); // [{ name: "Charlie" }, { name: "Bob" }]
console.log(shallowCopyArr); // [{ name: "Charlie" }, { name: "Bob" }]

 

3.깊은 복사 (Deep Copy)와 얕은 복사 (Shallow Copy)의 비교

 

복사 방식 객체의 모든 계층의 데이터를 복사함 최상위 계층(첫 번째 레벨)만 복사하고, 중첩된 객체는 참조 복사
독립성 복사된 객체가 원본 객체와 완전히 독립적임 중첩된 객체는 원본과 동일한 메모리 주소를 공유하여 의존성이 있음
원본 영향 여부 복사된 객체 수정 시 원본에 영향을 주지 않음 복사된 객체에서 중첩 객체 수정 시 원본에 영향을 미침
적용 사례 중첩된 구조(객체 안의 객체, 배열 안의 객체 등)를 복사할 때 적합 단순한 1차원 객체나 배열을 복사할 때 적합
복사 속도 및 메모리 더 많은 메모리와 시간이 필요함 상대적으로 빠르고 메모리 사용이 적음
구현 예시 JSON.parse(JSON.stringify(obj)), structuredClone(), lodash.cloneDeep() Object.assign(), 스프레드 연산자({ ...obj }), slice()
사용 시 주의점 깊은 중첩 구조의 객체에서만 필요하며, 속도와 메모리 소모가 큼 중첩 구조가 있으면 원본과의 의존성을 유발할 수 있음
반응형