COPY
프로그래밍을 공부하다보면 shallow copy(얕은 복사) deep copy(깊은 복사)를 경험하신적이 있으실것입니다.
c언어 에서는 포인터, java에서는 reference variable 등등 을 관리하고 데이터 처리를 할때 많이 만나게 됩니다.
대표적인 예를 javascript 에서 확인해보겠습니다.
Example ) Shallow Copy - 1
// A 라는 사람이 메모장을 쓴다고 했을때 가정을 해봅시다.
const memoA = { author: 'Person A', content: 'plan to make a coffee' };
// 그리고 B 라는 사람이 A 라는 사람의 메모장을 복사하여 받은 뒤 수정한다고 해봅시다.
const memoB = memoA;
// B라는 사람은 author, content 의 내용만 지우고 B 사람의 이름과 메모를 적습니다.
memoB.author = 'Person B';
memoB.content = 'take a bus';
// memoA의 값 까지 바뀌는 현상이 발생 했습니다.
console.log('memoA, ', memoA); // memoA, {author: 'Person B', content: 'take a bus'}
console.log('memoB, ', memoB); // memoA, {author: 'Person B', content: 'take a bus'}
// memoA 와 memoB가 같다고 나옵니다.
console.log(memoA === memoB) // true
// 이러한 현상을 reference copy (주소 복사), shallow copy(얕은 복사) 라고 하는데 왜 이런 문제가 발생할까요?
const aVar = 10;
상수로 aVar 데이터를 만들고 10의 값을 넣는다면 다음과 같이 aVar 변수 안에 10이라는 데이터가 존재합니다.
하지만 reference 데이터들인 Object.. Array.. 인 경우에는 다르게 동작을 합니다.
const memoA = {author: 'Person A', content: 'Plan to make a coffee'};
바로 객체의 주소를 가진다는 점입니다.
자바로 예를 든다면 참조 변수, 참조 한다고 합니다
const memoB = memoA;
그래서 만약 memoB 변수를 만들고 memoA 변수를 바로 대입을 하여 복사를 한다면 shallow copy (얕은 복사) 가 되어버립니다.
memoB.author = 'Person B';
memoB.content = 'Take a bus';
만약 이 상황에서 memoB의 객체 프로퍼티의 값을 변경한다면 어떻게 될까요?
memoB의 객체 프로퍼티 값들이 변경 되면서 memoA 또한 같은 주소를 가지고 있기 때문에 memoB만 변경을 했을뿐인데 memoA 까지 데이터가 변하게 된 이유 입니다.
이걸 방지하기 위해선 Deep Copy (깊은 복사) 를 해줘야 합니다.
Example ) Shallow Copy - 2
const memoA = { author: 'Person A', content: 'plan to make a coffee' };
const memoB = {...memoA};
memoB.author = 'Person B';
memoB.content = 'take a bus';
console.log('memoA, ', memoA); // memoA, {author: 'Person A', content: 'plan to make a coffee'}
console.log('memoB, ', memoB); // memoB, {author: 'Person B', content: 'take a bus'}
console.log(memoA === memoB) // false
console.log(memoA.author === memoB.author) // false
console.log(memoA.content === memoB.content) // false
내가 생각한 해결 방법 1. [ ES6 ] Spread Operator (스프레드 연산자) - Deep Copy가 아닙니다.
ES6 에서 나온 Spread Operator 을 사용하여 Deep Copy(깊은 복사)를 구현 할 수 없습니다.
Spread Operator 을 이용한다면 1차원 배열 or 객체만 데이터 복사가 됩니다.
다차원 배열, 객체로 들어간다면 Shallow Copy(얕은 복사)가 되어 버립니다.
const memoA = {
author: 'Person A',
content: ['one', 'two', 'three', 'four', 'five']
};
const memoB = {...memoA};
memoB.author = 'Person B';
memoB.content[1] = 'a';
console.log('memoA, ', memoA); // memoA, {author: 'Person A', content: ['one', 'a', 'three', 'four', 'five']}
console.log('memoB, ', memoB); // memoB, {author: 'Person B', content: ['one', 'a', 'three', 'four', 'five']}
console.log(memoA === memoB) // false
console.log(memoA.author === memoB.author) // false
console.log(memoA.content === memoB.content) // true
이렇게 1차원적인 객체 또는 배열은 원시 데이터로 복사가 되지만 다차원 배열 또는 객체의 경우 값이 변경이 되어버립니다.
Example ) Deep Copy
해결 방법 1. JSON 메소드 이용하기
const memoA = {
author: 'Person A',
content: ['one', 'two', 'three', 'four', 'five']
};
const memoB = JSON.parse(JSON.stringify(memoA));
memoB.author = 'Person B';
memoB.content[1] = 'a';
console.log('memoA, ', memoA); // memoA, {author: 'Person A', content: ['one', 'two', 'three', 'four', 'five']}
console.log('memoB, ', memoB); // memoB, {author: 'Person B', content: ['one', 'a', 'three', 'four', 'five']}
console.log(memoA === memoB) // false
console.log(memoA.author === memoB.author) // false
console.log(memoA.content === memoB.content) // false
const memoB = JSON.parse(JSON.stringify(memoA)); 이런식으로 JSON 메서드를 이용하여 string으로 바꾼다음 다시 json.parse로 바꿔서 원시 데이터 처럼 데이터를 복사 할 수 있습니다.
해결 방법 2. lodash
import _ from 'lodash';
const memoA = {
author: 'Person A',
content: ['one', 'two', 'three', 'four', 'five']
};
const memoB = _.cloneDeep(memoA);
memoB.author = 'Person B';
memoB.content[1] = 'a';
console.log('memoA, ', memoA); // memoA, {author: 'Person A', content: ['one', 'two', 'three', 'four', 'five']}
console.log('memoB, ', memoB); // memoB, {author: 'Person B', content: ['one', 'a', 'three', 'four', 'five']})
console.log(memoA === memoB) // false
console.log(memoA.author === memoB.author) // false
console.log(memoA.content === memoB.content) // false
자바스크립트에서 유명한 라이브러리중 하나인 lodash 를 이용하여 Deep Copy를 지원하는 메소드가 있습니다.
cloneDeep(); 이라는 메소드 입니다.
lodash는 _ 이라는 걸로 불러와서 많이들 쓰는것 같아서 _로 불러왔고 _.cloneDeep() 하여 인자에 복사할 데이터를 넣게 되면 Deep copy 를 할수있습니다.
Github: https://github.com/GangOn0215/dev-til/blob/main/JavaScript/Copy.md
'FrontEnd > JavaScript' 카테고리의 다른 글
Immutability (불변성) 에 대한 정리 - 4 (0) | 2022.05.14 |
---|---|
Immutability (불변성) 에 대한 정리 - 3 (0) | 2022.05.13 |
Immutability (불변성) 에 대한 정리 - 2 (0) | 2022.05.12 |
Immutability (불변성) 에 대한 정리 - 1 (0) | 2022.05.11 |
[ JS ] Date 함수를 사용하여 이번 주간, 월간 데이터 구하기 (0) | 2022.04.01 |