꼬꼬마 블로그

꼬꼬마의 기술 블로그

ES6의 전개 (spread 연산자)를 통해 손쉽게 깊은 복사를 할 수 있습니다.

 

하지만 과연 전개는 완전히 깊은 복사일까요? 오늘은 전개가 완전히 깊은 복사가 아닌 경우와 그에 따른 해결방법을 글에 남기도록 하겠습니다.

 

글에 앞서 Spread연산자에 대해 모른다면 아래의 글을 먼저 읽어주세요

 

[JS] Spread 연산자, Rest 파라미터

Spread 연산자 Spread 연산자는 ... 을 통해 사용할 수 있습니다. MDN에서는 아래와 같이 Spread 연산자를 설명합니다. 전개 구문을 사용하면 배열이나 문자열과 같이 반복 가능한 문자를 0개 이상의 인

wlswoo.tistory.com

 

전개로 깊은 복사가 되지 않는 경우

쉽게 말해 nested 되었을 경우 내부 중첩된 요소들은 깊은 복사가 되지 않습니다.

 

const a = {
  key: 'aVal'
}

const b = {
  ...a
}

b.key = 'bVal';

console.log(a);
console.log(b);

// { key: 'aVal' }
// { key: 'bVal' }

위는 깊은 복사가 진행된 경우 입니다. a를 전개한 값을 다시 객체로 묶어 b로 할당한다면 다른 객체를 참조하기에 b의 값을 바꿔도 a의 값이 바뀌지 않습니다.

 

const a = {
  out: {
    in: 'aVal'
  }
}

const b = {
  ...a
}

b.out.in = 'bVal';

console.log(a);
console.log(b);

// { out: { in: 'bVal' } }
// { out: { in: 'bVal' } }

하지만 위와 같이 객체 안에 또 다른 객체가 존재한다면 그 내부 객체는 깊은 복사가 되지 않습니다. 물론 아래와 같이 out에 대한 값을 바꾼다면 깊은 복사가 일어납니다

 

const a = {
  out: {
    in: 'aVal'
  }
}

const b = {
  ...a
}

b.out = null;

console.log(a);
console.log(b);

// { out: { in: 'aVal' } }
// { out: null }

 

 

위와 같은 경우는 배열또한 마찬가지 입니다.

const a = [
  {
    key: 'aVAl'
  }
]

const b = [
  ...a
]

b[0].key = 'bVal';

console.log(a);
console.log(b);

// [ { key: 'bVal' } ]
// [ { key: 'bVal' } ]

배열의 바로 요소가 아닌 요소의 프로퍼티를 바꾼다면 기존의 값도 바뀌는 것을 알 수 있습니다.

 

 

nested된 객체 깊은 복사

1. JSON을 이용

const a = {
  out: {
    in: 'aVal'
  }
}

const b = JSON.parse(JSON.stringify(a))

b.out.in = 'bVal';

console.log(a);
console.log(b);

// { out: { in: 'aVal' } }
// { out: { in: 'bVal' } }

위와 같이 JSON.parseJSON.stringify를 이용하면 깊은 복사를 할 수 있습니다.

JSON.stringify는 객체를 Json 문자열로 바꿔주며 JSON.parse는 Json문자열을 객체로 바꿔주는 함수입니다.

 

하지만 위의 방식은 성능이 느리고 만약 프로퍼티의 value가 function이라면 JSON.stringify중  undefined로 처리됩니다.

 

2. Lodash 패키지

NPM의 Lodash 패키지를 이용하는 방식입니다.

엄청나게 많은 사람이 다운받아 사용하여 이미 검증된 패키지입니다.

 

많은 메소드가 있지만 cloneDeep이라는 메소드를 이용합니다.

 

const { cloneDeep } = require('lodash')

const a = {
  out: {
    in: 'aVal'
  }
}

const b = cloneDeep(a)

b.out.in = 'bVal';

console.log(a);
console.log(b);

// { out: { in: 'aVal' } }
// { out: { in: 'bVal' } }

위와 같이 간단히 cloneDeep이라는 함수로 간단히 사용할 수 있습니다.

 


참조 문서

junwoo45.github.io/2019-09-23-deep_clone/