[JavaScript] 얕은 복사, 깊은 복사

얕은 복사와 깊은 복사를 알기위해서는 기본적으로 원시 데이터 타입과 참조 데이터 타입에 대해서 알아야 한다.


원시 데이터 타입(Primitive type)

- String
- Number
- Boolean
- Null
- Undefined

참조 데이터 타입(Reference type)

- Object
- Symbol



원시 데이터 타입의 경우 값을 복사하면 새로운 메모리에 값을 할당하기 때문에 원본과 복사된 값 둘 간의 영향을 미치지않는다.

let ex1 = "apple";

let ex2 = ex1;

ex1 = "banana";

console.log("ex1 =>", ex1); // ex1 => banana
console.log("ex2 =>", ex2); // ex2 => apple

반면에 참조 데이터 타입은 해당 객체의 메모리 주소 값을 복사하기 때문에 원본과 복사된 값 둘중 하나라도 값의 변경이 일어나면 원본과 복사본 모두 변경사항이 반영된다.

let person1 = {
name: "Kim",
age: "11",
};

let person2 = person1;

person1["name"] = "Park";

console.log("person1 =>", person1); // person1 => { name: 'Park', age: '11' }
console.log("person2 =>", person2); // person2 => { name: 'Park', age: '11' }


객체의 경우 이러한 특성 때문에 객체를 복사하는 방법이 크게 두가지로 나뉜다.



얕은 복사 shallow copy


얕은 복사는 최상위 객체의 참조를 끊는게 얕은 복사이다.
최상위 객체의 참조를 끊더라도 객체안에 객체가 있는 경우 한개의 객체라도 원본 객체를 참조하고 있다면 이는 얕은 복사이다.

얕은 복사를 하는 방법에는 대표적으로 아래 두가지 방법이 있다.


1. Object.assign()

const obj = {
a: 1,
b: {
c: 2,
},
};

const copiedObj = Object.assign({}, obj);

copiedObj.b.c = 3

obj === copiedObj // false
obj.b.c === copiedObj.b.c // true

예시에서 알 수 있듯 최상위 객체의 경우 비교시 다른 값(메모리 주소)으로 나타나지만 객체 내부의 객체의 경우 원본 객체의 값(메모리 주소)을 참조하고 있다.



2. 전개연산자

const obj = {
a: 1,
b: {
c: 2,
},
};

const copiedObj = {...obj}

copiedObj.b.c = 3

obj === copiedObj // false
obj.b.c === copiedObj.b.c // true

전개연산자 또한 위 Object.assign()과 동일하게 동작한다.




깊은 복사 deep copy


깊은 복사는 최상위 객체의 참조 뿐만아니라 객체 내부 안의 존재하는 모든 객체까지 전부다 참조를 끊는 복사이다.

깊은 복사하는 방법에는 대표적으로 아래 세가지 방법이 존재한다.


1. 재귀함수를 이용한 복사

const obj = {
a: 1,
b: {
c: 2,
},
};

function copyObj(obj) {
const result = {};

for (let key in obj) {
if (typeof obj[key] === 'object') {
result[key] = copyObj(obj[key]);
} else {
result[key] = obj[key];
}
}

return result;
}

const copiedObj = copyObj(obj);

copiedObj.b.c = 3

obj.b.c === copiedObj.b.c //false


2. JSON.stringify()

객체를 json 형식의 문자열로 변환하는데 이 과정에서 원본 객체와의 참조가 모두 끊어진다.
객체를 json 형식의 문자열로 변환했다가 JSON.parse를 사용해 다시 객체로 만들어주면 깊은 복사가 가능하다.

하지만 다른 방식에비해 속도가 느리다고 알려져있다.

const obj = {
a: 1,
b: {
c: 2,
},
};

const copiedObj = JSON.parse(JSON.stringify(obj));

copiedObj.b.c = 3

obj.b.c === copiedObj.b.c //false


3. lodash 라이브러리 사용

lodash 라이브러리를 사용하면 깊은 복사를 더 쉽게 할 수 있다.

const obj = {
a: 1,
b: {
c: 2,
},
};

const copiedObj = _.cloneDeep(obj);

copiedObj.b.c = 3

obj.b.c === copiedObj.b.c //false




댓글