얕은 복사는 원본 객체의 속성들을 새로운 객체에 복사하지만, 속성 값이 객체나 배열인 경우에는 참조(주소)가 복사되므로 내부 객체는 동일한 참조를 공유한다. 반면에 깊은 복사는 원본 객체 및 모든 중첩된 객체와 배열까지 모두 새로운 객체에 복사하는 방식이다.
JSON.stringify()
와 JSON.parse()
를 사용하여 객체를 문자열로 변환하고 다시 파싱하여 깊은 복사를 수행할 수 있다. 이 방법은 간단하지만, 함수나 정규표현식, Date
같은 특별한 객체 타입을 다루기 어렵다. 또한 성능적으로, 비교적 큰 계산이 이루어지기에 지양해야 한다.
const originalObject = { key: 'value', nested: { innerKey: 'innerValue' } };
// 깊은 복사, 다른 주소를 가진 객체가 깊게 복사됨.
const deepCopy = JSON.parse(JSON.stringify(originalObject));
키값이 객체거나 배열이면 재귀함수를 실행하여 새로운 값을 대입해준다. 이 방법은 객체의 크기에 따라 성능이 달라질 수 있다. 또한, 순환 참조와 같은 특별한 경우에 대한 처리가 필요할 수 있습니다.
function deepCopy(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
const copy = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key]);
}
}
return copy;
}
const originalObject = { key: 'value', nested: { innerKey: 'innerValue' } };
// 깊은 복사
const deepCopy = deepCopy(originalObject);
몇 가지 라이브러리는 깊은 복사를 수행하기 위한 특별한 메서드를 제공한다. 예를 들어, Lodash의 _.cloneDeep
함수가 있다. 일반 개발에서는 효율적이겠지만, 코딩 테스트 용으로는 알맞지 않다.
import { cloneDeep } from 'lodash';
const originalObject = { key: 'value', nested: { innerKey: 'innerValue' } };
// 깊은 복사
const deepCopy = cloneDeep(originalObject);
structuredClone()
는 javascript의 내장된 깊은 복사 함수이다. 이전에는 이 함수가 js에서 제공되지 않았기 때문에 다른 방법을 사용해야 했었다. 하지만 비교적 최근 업데이트된 HTML 명세는 구조화된 복제 알고리즘을 실행하는 structuredClone()
이라는 함수를 제공되어 편의성을 증가시켰다.
또한, Date
, Set
, Map
, Error
, RegExp
, 등 다양한 JavaScript 유형을 복제시켜준다.
즉,
structuredClone()
의 등장으로 에서 값의 깊은 복사본을 생성해야 하는 경우, 더 이상 다른 라이브러리를 활용하지 않아도 된다. JS 생태계에서 제공하는 structuredClone()로 사용하면 된다.