Javascript에서 데이터를 복사할 때, 두 가지 개념이 존재한다.
바로 얕은 복사(Shallow Copy)
와 깊은 복사(Deep Copy)
이다.
이전에도, 한번 이 복사에 대해 학습한 적이 있었는데 이번 기회에 다시 공부하면서 확실히 알게 되었다.
스프레드 연산자(...)를 사용하면 기존 배열이나 객체의 전체 또는 일부를 다른 배열이나 객체로 빠르게 복사할 수 있다.
아래와 같은 상황에서 사용할 수 있음.
const user = { name: 'Kwon', city: 'ABC' };
//age 프로퍼티 추가
user = { ...user, age: 24 };
console.log (user); // { name: 'Kwon', city: 'ABC', age: 24 }
//프로퍼티 값 수정 및 프로퍼티 추가
user = { ...user, name: 'kim', age: 24 }
console.log(user); // { name: 'Kim', city: 'abc', age: 24 }
스프레드 연산자(...)는 얕은 복사
를 진행한다. (즉, 원본과 복사본이 서로 영향을 주고 받는다)
const profile = {
name : "KDH",
age: 24
}
위와 같은 profile 객체가 있을 때
const profile2 = profile;
이 때, profile2는 profile의 객체 주소(번지)를 함께 가리키게 된다.
만약 profile2의 name을 수정하면 원본인 profile의 name도 수정된다.
이를 해결하기 위한 2가지 방법이 있다.
//방법1) 직접 (원시)값을 할당
const profile2 = {
name: profile.name,
age: profile.age
}
//방법2) 스프레드 연산자 사용
const profile3 = {
...profile
}
위처럼, 2가지 방식을 이용하면 원본과 복사본 서로 영향을 주지 않는다.
그러나, 객체 안에 객체가 있는 경우는 또 다르다.
const profile4 = {
...profile,
hobby: {
hobby1:"수영",
hobby2:"축구"
}
}
const profile5 = {
...profile4
}
profile4와 profile5는 서로 영향을 주지 않을까?
먼저, name 프로퍼티부터 수정해보았다.
서로 영향을 주지 않는다!
다음으로, hobby 객체의 hobby1을 수정해보았다.
hobby 객체를 수정하니까, 원본인 profile4의 hobby 객체도 수정되는 것을 알 수 있다.
이처럼, 서로 분리된 각각의 객체를 가리키는 것이 아니라 하나의 객체를 공유하도록 복사하는 것을 얕은 복사(shallow copy)라고 한다.
위에서 보았듯이 객체 안에 객체 즉, 중첩 객체를 복사(원본과 복사본 서로 영향을 안주는 복사)하기 위해서는 깊은 복사가 필요하다.
JSON.stringify 메서드는 객체를 통째로 JSON 문자열로 변환해주는 역할을 한다.
JSON.parse 메서드는 JSON 문자열을 JavaScript 객체로 변환해주는 역할을 한다.
원본과 복사본이 서로 영향을 주고 받지 않게 되었다 즉, 깊은 복사가 완료되었다!
lodash
https://www.npmjs.com/package/lodash
객체를 복사할 때마다 깊은 복사를 따로 해주기는 번거롭고 느릴 수 있다.
이를 도와주기 위해 lodash와 같은 라이브러리들이 많이 나와있다.
lodash에서 제공하는 _.cloneDeep(value)을 사용하면 손쉽게 깊은 복사를 할 수 있다.