깊은 복사, 얕은 복사

김현준·2024년 3월 11일
0

자바스크립트

목록 보기
6/20

얕은 복사와 깊은 복사는 데이터의 복사 방법에 대한 개념으로, 원시값과 객체를 다룰 때 각각 다르게 동작한다. 이를 쉽게 설명하면 다음과 같다:

원시값 복사

let num1 = 1;
let num2 = num1; // num2에 num1의 값을 복사
num2 = 2;

console.log(num1, num2); // num1: 1, num2: 2

이 경우 num1과 num2는 독립적인 값을 가진다. num2를 변경해도 num1에 영향을 주지 않는다. 이는 원시값의 특성 때문이다.

얕은 복사

  • 객체나 배열을 복사할 때 최상위 레벨(1-depth)만 복사(map 메서드 등)
  • 중첩된 객체나 배열은 원본과 동일한 참조를 공유하는 복사 방식
const mike = {
  name: 'mike',
  age: 12,
};

let user = mike; // mike의 참조를 user에 복사
user.age = 14;

console.log(mike, user);
// { name: 'mike', age: 14 } { name: 'mike', age: 14 }

여기서 user는 mike와 동일한 객체를 가리킨다. 따라서 user의 값을 변경하면 mike의 값도 함께 변경된다.

얕은 복사를 수행하는 메서드와 연산자(1-depth)

  • 얕은 복사를 수행하는 메서드와 연산자는 객체나 배열의 복사 시 최상위 레벨만 복사하지만, 원본과의 연결을 끊는 새로운 데이터 구조를 생성한다.
  • 객체안에 객체가 있을 경우 한개의 객체라도 원본 객체를 참조하고 있다면 이를 얕은 복사라고 한다.
    ㅤㅤ
    예제: 얕은 복사를 수행하는 메서드
const original = {
  name: 'mike',
  age: 12,
  details: { hobby: 'soccer' },
};// 얕은 복사 (최상위 레벨만 복사)
const shallowCopy = { ...original };// 수정
shallowCopy.name = 'john';
shallowCopy.details.hobby = 'basketball';
ㅤ
console.log(original);
// { name: 'mike', age: 12, details: { hobby: 'basketball' } }
ㅤ
console.log(shallowCopy);
// { name: 'john', age: 12, details: { hobby: 'basketball' } }
  • shallowCopy.name은 독립적으로 복사되었으므로, 변경해도 원본에는 영향을 미치지 않는다.
  • 하지만 중첩된 객체인 details는 참조를 공유하므로, 내부 속성 hobby를 변경하면 원본에도 영향을 미친다.

깊은 복사

깊은 복사는 객체나 배열을 복사할 때 중첩된 데이터까지 모두 새로운 메모리에 복사하는 방식이다.
원본과 복사본은 완전히 독립적이다.

const mike = {
  name: 'mike',
  age: 12,
};

const user = JSON.parse(JSON.stringify(mike)); // 깊은 복사
user.age = 14;

console.log(mike, user);
// { name: 'mike', age: 12 } { name: 'mike', age: 14 }

깊은 복사를 사용하면 user와 mike는 독립적인 객체가 되어, 한쪽을 변경해도 다른 쪽에 영향을 미치지 않는다.

JSON.stringify를 이용해 깊은 복사를 하고 데이터를 수정한 예시

// 원본 객체
const original = {
  name: 'Alice',
  age: 25,
  address: {
    city: 'New York',
    zip: '10001',
  },
};// JSON.stringify와 JSON.parse를 이용해 깊은 복사
const deepCopy = JSON.parse(JSON.stringify(original));// 복사본 데이터 수정
deepCopy.name = 'Bob';
deepCopy.address.city = 'Los Angeles';// 결과 확인
console.log('Original:', original);
console.log('Deep Copy:', deepCopy);// 출력 결과
// Original: { name: 'Alice', age: 25, address: { city: 'New York', zip: '10001' } }
// Deep Copy: { name: 'Bob', age: 25, address: { city: 'Los Angeles', zip: '10001' } }

동작 원리
1. JSON.stringify(original)
객체를 JSON 문자열로 변환하여, 객체의 구조와 데이터를 문자열 형태로 저장한다.
2. JSON.parse()
JSON 문자열을 다시 객체로 변환한다. 이 과정에서 원본 객체의 모든 값을 복사하여 새로운 객체를 생성한다.

원시값은 깊은 복사, 객체는 얕은 복사인 이유

  • 원시값은 깊은 복사
    원시값은 데이터 크기가 작아, 복사 과정에서 독립적인 값을 생성해도 큰 비용이 들지 않는다. 따라서 원시값은 기본적으로 깊은 복사를 한다.

  • 객체는 얕은 복사
    객체는 데이터 크기가 크고, 중첩된 구조를 가질 수 있다. 만약 객체를 항상 깊은 복사한다면 성능에 큰 영향을 줄 수 있다.

비효율성의 예

const mike = {
  name: 'mike',
  age: 12,
  address: {
    city: 'Seoul',
    zip: '12345',
  },
};

let user = mike; // mike의 참조만 복사

만약 이 데이터를 깊은 복사로 처리했다면, 다음과 같은 새로운 객체를 생성해야 한다

let user = {
  name: 'mike',
  age: 12,
  address: {
    city: 'Seoul',
    zip: '12345',
  },
};

이처럼 모든 속성을 새로 복사하면 데이터 크기가 클수록 성능 부담이 크다.

얕은 복사의 장점

  • 객체를 얕은 복사로 다루면 단순히 원본 객체의 참조를 공유하므로 메모리 사용량과 처리 시간이 줄어든다.
  • 동일한 데이터를 공유하는 경우, 참조를 통해 효율적으로 값을 확인할 수 있다.

요약

  • 원시값은 깊은 복사를 통해 독립적인 값을 가진다.
  • 객체는 얕은 복사로 참조를 공유하며, 성능 효율성을 위해 원본과 복사본이 동일한 데이터를 참조한다.
  • 깊은 복사가 필요한 경우는 JSON.stringify 또는 라이브러리를 사용해 명시적으로 처리해야 한다.
profile
기록하자

0개의 댓글

관련 채용 정보