[EXT-038][실무] 중첩된 자료를 안전하게 깊이 복사하기 > IT 기술 공유

본문 바로가기
사이트 내 전체검색

IT 기술 공유

[EXT-038][실무] 중첩된 자료를 안전하게 깊이 복사하기

페이지 정보

profile_image
작성자 기술팀장
댓글 0건 조회 2회 작성일 26-09-09 04:36

본문

[이번 수업]
객체를 펼침 문법으로 복사해도 안쪽 배열과 객체는 원본과 함께 바뀔 수 있습니다. 이번에는 structuredClone()으로 중첩된 자료를 깊이 복사하고, 큰 바이트 버퍼는 복사 대신 옮기는 방법을 배웁니다.

[선수지식]
JavaScript 객체·배열·Map, 참조와 얕은 복사의 뜻을 알아야 합니다. Node.js 17 이상에서 예제를 실행할 수 있습니다.

[학습목표]
1. 얕은 복사와 깊은 복사의 차이를 확인합니다.
2. Date, Map, 순환 참조를 복사합니다.
3. ArrayBuffer를 transfer 목록으로 옮깁니다.

[핵심개념]
깊은 복사는 안쪽 값까지 새 구조로 만드는 일입니다. structuredClone(value)는 HTML 표준의 구조화 복제 알고리즘으로 깊은 복사본을 반환합니다. Date와 Map 같은 지원 자료형을 그 자료형으로 보존하고, 객체가 자신을 다시 가리키는 순환 참조도 처리합니다. JSON.stringify()와 JSON.parse()를 잇는 방식은 Date를 문자열로 바꾸고 Map의 항목을 보존하지 못하며 순환 참조에서 실패하므로 범용 복사법이 아닙니다.

모든 값이 복제되지는 않습니다. 함수처럼 직렬화할 수 없는 값이 섞이면 DataCloneError인 DOMException이 발생합니다. 사용자 정의 클래스의 동작과 원형도 그대로 복제된다고 기대하면 안 됩니다.

두 번째 인수의 transfer 목록에 ArrayBuffer를 넣으면 바이트를 복제하지 않고 새 소유자에게 이전합니다. 이전 뒤 원본 버퍼는 분리되어 byteLength가 0이 되므로 다시 사용하면 안 됩니다.

[따라하기]
다음을 clone-data.mjs로 저장합니다.

```js
const source = {
  user: { tags: ['입문'] },
  createdAt: new Date('2026-01-02T03:04:05Z'),
  scores: new Map([['js', 90]]),
};
source.self = source;

const copy = structuredClone(source);
copy.user.tags.push('실무');

console.log(source.user.tags.join(','));
console.log(copy.createdAt instanceof Date);
console.log(copy.scores.get('js'));
console.log(copy.self === copy);

const buffer = new Uint8Array([10, 20, 30]).buffer;
const moved = structuredClone(buffer, { transfer: [buffer] });
console.log(`${buffer.byteLength}->${moved.byteLength}`);
```

터미널에서 node clone-data.mjs를 실행합니다. Windows PowerShell, macOS Terminal, Linux 셸의 명령은 같습니다. 예상 결과입니다.

```text
입문
true
90
true
0->3
```

복사본의 태그를 바꿔도 원본은 입문 하나만 남습니다. self는 복사본 자신을 가리키고, 마지막 줄은 3바이트가 새 버퍼로 이전되었음을 뜻합니다. Node.js v25.8.1에서 확인했습니다.

[흔한 실수]
{ ...source }만 쓰면 첫 단계만 복사되어 중첩 값은 공유됩니다. JSON 왕복을 깊은 복사의 만능 도구로 쓰지 마세요. 함수가 들어 있는 값을 바로 복제하면 DataCloneError가 납니다. transfer한 원본 버퍼를 뒤에서 다시 읽는 실수도 피해야 합니다. 필요한 자료형이 지원되는지 먼저 작은 값으로 시험하세요.

[보안 주의]
structuredClone()은 입력 검증이나 악성 값 정리를 대신하지 않습니다. 신뢰하지 않는 입력은 허용한 키·자료형·길이를 먼저 검사하세요. 매우 큰 객체를 반복 복제하면 메모리와 CPU를 소모하므로 크기와 횟수도 제한합니다. 비밀정보를 복제하면 메모리에 사본이 늘어나며, 다른 코드가 계속 써야 하는 버퍼는 transfer하지 않습니다. 실습은 본인 소유의 로컬 자료로 진행합니다.

[직접 해볼 과제]
source에 Set과 중첩 객체를 추가한 뒤 복사본만 수정해 원본이 그대로인지 확인하세요. 이어 structuredClone({ run() {} })을 try/catch로 감싸고 오류 이름이 DataCloneError인지 출력합니다.

[확인문제]
1. 펼침 문법으로 만든 얕은 복사에서 중첩 배열이 원본과 함께 바뀌는 이유는 무엇인가요?
2. transfer한 ArrayBuffer의 원본 byteLength가 0이 되는 이유는 무엇인가요?
3. structuredClone()이 입력 검증을 대신할 수 없는 이유는 무엇인가요?

[다음 학습]
다음에는 구조화 복제와 Worker 메시지를 연결해 큰 계산을 다른 실행 흐름으로 안전하게 넘깁니다.

[공식 참고 자료]
- WHATWG HTML Standard — Structured cloning API: https://html.spec.whatwg.org/multipage/structured-data.html#structured-cloning-api
- WHATWG HTML Standard — Transferable objects: https://html.spec.whatwg.org/multipage/structured-data.html#transferable-objects
- Node.js Global objects — structuredClone(): https://nodejs.org/api/globals.html#structuredclonevalue-options

댓글목록

등록된 댓글이 없습니다.

회원로그인

회원가입

사이트 정보

회사명 : 회사명 / 대표 : 대표자명
주소 : OO도 OO시 OO구 OO동 123-45
사업자 등록번호 : 123-45-67890
전화 : 02-123-4567 팩스 : 02-123-4568
통신판매업신고번호 : 제 OO구 - 123호
개인정보관리책임자 : 정보책임자명

접속자집계

오늘
3,840
어제
6,862
최대
16,772
전체
769,791
Copyright © 소유하신 도메인. All rights reserved.