얕은 복사 && 깊은 복사

이상민·2024년 11월 28일

TIL

목록 보기
47/50

들어가기 전에

자바스크립트의 데이터 타입에는 원시타입(primitive type), 참조타입(object/reference type) 두가지 타입이 존재한다.

원시타입에는 string, number, bigint, boolean, undefined, symbol, (null) 7가지 타입이 있는데,
원시 값을 변수에 할당하면 변수는 메모리(stack 영역)에 실제 값을 저장하며, 참조타입에는 배열, 객체, 함수 등이 있다.
객체를 변수에 할당하면 변수는 메모리(stack 영역)에 참조값(주소값, reference)을 저장하고 이 참조값(주소값)은 메모리의 heap 영역에 저장된 데이터를 가리킨다.

각 데이터타입을 복사할 때 생기는 일

원시값을 복사할 때 원시값을 복사한 값은 또 다른 독립적인 메모리 공간에 할당되기 때문에, 복사 및 값을 수정해도 기존 원시값을 저장한 변수에는 영향을 끼치지 않는다. 이러한 실제 값을 복사하는 것은 깊은 복사라고 한다.

또한 자료형(참조값)을 복사할 때 변수가 객체의 참조(주소)를 가리키고 있기 때문에, 복사된 변수도 동일하게 객체가 저장된 메모리 공간의 참조(주소)를 가리키고 있다. 복사 및 값을 수정하면 수정 전/후의 변수가 가리키고 있는 주소값이 같기 때문에 기존 객체를 저장한 변수에 영향을 끼칩니다. 이렇게 객체의 참조값(주소값)을 복사하는 것을 얕은 복사라고 한다. 아래에서 얕은복사와 깊은복사의 사전적 의미를 다시 알아보자.

얕은 복사 (Shllow Copy)

얕은 복사란 ?

객체의 얕은 복사는 복사된 객체의 속성이 원본 객체와 같은 참조값을 가지고 있는 복사를 뜻한다. 얕은 복사가 되었을 경우 원본 객체와 복사된 객체 중 어느 것을 변경하더라도 다른 객체가 동일하게 변경하게 되는데 이것은 의도치 않은 원본 객체나 복사된 객체의 변경을 야기할 수 있으며, 깊은 복사를 사용해서 방지할 수 있다.

얕은 복사 방법

1) Array.prototype.slice()
배열 복사 시 사용.

2) Object.assign()
객체 복사 시 사용.

3) 전개 연산자(spread syntax)
...{}

깊은 복사 (Deep Copy)

깊은 복사란 ?

깊은복사는 객체의 깊은 복사는 복사된 객체의 속성이 원본 객체와 같은 참조값을 공유하지 않는 복사를 뜻한다. 깊은 복사가 되었을 경우 원본 객체와 복사된 객체 중 어느 것을 변경하더라도 다른 객체에 영향을 미치지 않으며, 깊은 복사는 의도치 않은 원본 객체나 복사된 객체의 변경을 방지할 수 있다.

깊은 복사 방법

1) JSON.stringify() -> JSON.parse()
JSON.stringify() 로 객체를 JSON 문자열으로 변환했다가(이 과정에서 원본 객체와의 참조가 모두 끊어집니다), JSON.parse()로 다시 새로운 Javascript 객체로 변환하는 방법입니다.

장점 : 간단하고 쉽다는 장점이 있지만,
단점 : 다른 방법에 비해 비교적 느리고, 객체가 finction 일 경우 undefined 로 처리하는 단점이 있다.

2) 재귀함수를 이용한 복사
복잡하다.. 나중에 알아보자.

3) Lodash 라이브러리 사용
Lodash의 clonedeep 라는 메소드를 이용하면 Deep Copy가 가능하다.
JSON.parse(JSON.stringify()) 방법의 문제점이였던 함수 복사도 가능하다.

정리

얕은 복사는 원본 객체의 주소값을 복사하여 원본 객체와 복사된 객체가 같은 주소값을 가리키게 되고, 둘 중 하나가 변경될 경우 다른 값도 같이 변경된다.
얕은 복사의 방법에는 spread 구문, slice(). assign() 등이 있으며,

깊은 복사는 원본 객체의 값 자체가 복사되어 다른 주소값을 가지게 된다. 그래서 둘 중 하나가 변경되어도 서로 영향을 미치지 않아서 의도치않은 원본 객체나 복사된 객체의 변경을 방지할 수 있고, 상태의 변경을 추적하기 쉽다. 원시자료형은 기본적으로 깊은 복사가 되며,
깊은 복사의 방법에는 JSON.stringify() -> JSON.parse() 사용, 재귀함수 이용, Lodash 라이브러리 사용 등이 있다.

0개의 댓글