블로그로 돌아가기
Javascript

javascript deep copy 실무 가이드: 개념·예제·주의점

javascript deep copy를 실무에서 정확히 이해하고 적용하는 방법을 단계별로 정리합니다. 개념, 코드 예제, 비교표, 체크리스트와 성능·보안 주의점을 포함해 바로 쓸 수 있도록 구성했습니다.

deep copystructuredClonelodashimmutable datacircular reference
자바스크립트 deep copy 개념과 코드 예제가 포함된 기술 블로그 썸네일

javascript deep copy이 필요한 상황

javascript deep copy는 객체나 배열의 중첩된 값을 원본에 영향을 주지 않고 복제해야 할 때 필수입니다. 이 글에서는 javascript deep copy의 개념, 주요 방법(structuredClone, JSON 방법, lodash 등), 실무 코드 예제, 비교표, 체크리스트, 성능·보안·운영 관점의 주의점까지 다룹니다. 독자는 어떤 방법을 선택해야 하는지 판단하고 바로 적용할 수 있습니다.

javascript deep copy 핵심 개념

깊은 복사(deep copy)란 복제된 객체 내부의 모든 중첩 객체까지 새 인스턴스로 복사하는 것을 뜻합니다. 얕은 복사(shallow copy)는 최상위 속성만 복사하고 중첩된 객체는 원본과 참조를 공유합니다. 자바스크립트에서 값 타입(원시값)은 기본적으로 복사되지만 객체, 배열, 함수 등 참조 타입은 복사 방식에 따라 원본을 변경할 수 있습니다.

핵심 포인트:

  • 참조 공유로 인한 부작용 방지
  • 순환(circular reference) 처리 필요 여부
  • 함수, Symbol, Date, RegExp, Map/Set 등 비원시 타입 처리 방법

javascript deep copy 실무 예제

아래 예제는 다양한 방법을 보여줍니다: JSON 방법, structuredClone, lodash cloneDeep, 수동 구현(재귀) 예시.

// 예제 입력 데이터 const obj = { a: 1, b: { c: 2 }, d: [3, { e: 4 }], f: new Date('2020-01-01'), }; // 1) JSON stringify/parse (단순, 함수/undefined/Date/Map/Set/순환 미지원) const jsonCopy = JSON.parse(JSON.stringify(obj)); // 2) structuredClone (현대 브라우저/Node 17+ 지원) // 브라우저: structuredClone(obj) // Node.js: globalThis.structuredClone(obj) 또는 util의 structuredClone const structuredCopy = structuredClone(obj); // 3) lodash cloneDeep 사용 // import { cloneDeep } from 'lodash'; // const lodashCopy = cloneDeep(obj); // 4) 재귀 수동 복사 (순환 참조 처리 필요) function deepClone(value, map = new WeakMap()) { if (value === null || typeof value !== 'object') return value; if (map.has(value)) return map.get(value); if (value instanceof Date) return new Date(value); if (value instanceof RegExp) return new RegExp(value); if (Array.isArray(value)) { const arr = []; map.set(value, arr); for (const v of value) arr.push(deepClone(v, map)); return arr; } const result = {}; map.set(value, result); for (const key of Object.keys(value)) { result[key] = deepClone(value[key], map); } return result; } const manualCopy = deepClone(obj); console.log(jsonCopy, structuredCopy, manualCopy);

방법별 비교표

구분항목1항목2항목3
내용JSON stringify/parsestructuredClonelodash cloneDeep
내용간단, 속도가 빠름(단순 구조)표준, 순환 지원, 대부분 타입 지원널리사용, 다양한 타입 지원, 안정적
내용Date/RegExp/Map 등 비지원, 순환 에러브라우저/Node 버전 제한번들 크기 증가 가능

언제 쓰면 좋고 언제 피해야 할까

  • 언제 쓰면 좋은가:

    • 상태 관리에서 불변성 유지가 필요할 때
    • API 응답을 가공하기 전에 원본을 보호해야 할 때
    • 테스트에서 의도치 않은 사이드 이펙트를 방지할 때
  • 언제 피해야 하는가:

    • 매우 큰 객체(수십 MB 이상)를 자주 복사해야 할 때(비용 큼)
    • 함수/클로저 내부 상태를 그대로 복제해야 할 때
    • 순환 참조가 있고 간단한 문자열 변환 방식으로는 표현할 수 없을 때

실무 체크리스트

  • 복사할 데이터의 타입을 확인했는가? (Date, RegExp, Map/Set 등)
  • 순환 참조가 있는가? structuredClone 또는 순환 처리 로직이 필요한가?
  • 성능 민감 경로(랜더링 루프, 대량 처리)에서 복사 빈도를 줄였는가?
  • 외부 라이브러리(lodash) 도입 시 번들 영향과 버전 호환을 검토했는가?
  • 보안상 민감한 내용(토큰 등)을 복사해 클라이언트에 노출하지 않는가?

성능·보안·운영 주의점

성능:

  • JSON 방법은 단순 구조에서 빠르지만, 중첩이 깊거나 큰 데이터에서 메모리와 CPU 비용이 큽니다.
  • structuredClone는 브라우저/Node 구현에 따라 최적화되어 있고 순환 참조도 처리하지만, 지원 범위를 확인해야 합니다.
  • lodash cloneDeep은 신뢰성이 높지만 대량 데이터에서 비용이 발생합니다. 필요할 때만 사용하세요.

보안:

  • 객체 내 민감한 값(예: 토큰, 비밀번호)을 불필요하게 복제하여 로그/전송하지 않도록 주의합니다.
  • 외부 입력을 복사할 때 prototype pollution 공격 가능성을 고려해 안전한 복제가 필요합니다.

운영:

  • Node 버전이나 브라우저 지원을 기준으로 구현 전략을 정하세요. structuredClone가 없으면 폴리필 또는 라이브러리를 고려합니다.
  • 서버 측에서 대량 복제가 필요하면 스트리밍 변환이나 부분 복사 전략(필요 필드만 복사)을 사용하세요.

javascript deep copy 구현 판단 기준

구분항목1항목2항목3
내용단순 데이터중첩/순환 필요특수 타입(Date/Map 등)
내용JSON 방법 가능structuredClone 또는 재귀 필요lodash or 커스텀 로직 권장

자주 묻는 질문

Q1: JSON stringify/parse로 항상 복제해도 되나요? A1: 아니요. JSON 방식은 함수, undefined, Symbol, Date, Map/Set, 순환 참조를 지원하지 않습니다. 데이터 구조가 단순한 경우에만 사용하세요.

Q2: structuredClone와 lodash cloneDeep 중 무엇을 선택해야 하나요? A2: 브라우저/Node 환경에서 structuredClone을 사용할 수 있으면 우선 고려하세요(순환 지원, 성능 이점). 지원하지 않으면 lodash cloneDeep 또는 신뢰할 수 있는 재귀 구현을 사용하세요.

Q3: 순환 참조가 있는 데이터를 복사하려면 어떻게 해야 하나요? A3: structuredClone은 순환을 자동으로 처리합니다. 수동 구현 시 WeakMap을 사용해 방문 노드를 추적하고 순환 참조를 복원해야 합니다.

Q4: 복사 성능 최적화 팁이 있나요? A4: 불필요한 전체 복사를 피하고 필요한 필드만 복사하거나 구조 분해로 얕은 복사를 활용하세요. 빈번한 복사는 메모리 할당을 증가시키므로 캐시나 변경점(diff) 적용 방법을 검토하세요.

정리

  • javascript deep copy는 참조 공유로 인한 사이드 이펙트를 방지하기 위해 필요하다.
  • 방법별 장단점: JSON(간단하지만 제한적), structuredClone(표준적이고 순환 지원), lodash cloneDeep(광범위 타입 지원).
  • 실무에서는 데이터 타입, 순환 여부, 성능 요구를 기반으로 방법을 선택하라.
  • 체크리스트와 예제 코드를 통해 바로 적용할 수 있다.