728x90
JavaScript 배열 복사: spread와 map의 차이 완벽 정리 (얕은 복사 vs 깊은 복사)
실무에서 데이터를 다룰 때, 원본 배열을 복사하여 수정하는 작업은 자주 발생합니다.
하지만 단순히 복사했다고 생각한 배열이 의도치 않게 원본에 영향을 주는 경우도 있습니다.
이 글에서는 JavaScript에서 많이 사용되는 스프레드 연산자 (...
)와 map()
함수를 활용한 복사 방식의 차이를 정리해보겠습니다.
예시 코드
// 1. Spread 문법 사용
const newList = [...rawMemberTypeList];
// 2. map + Spread 사용
const newList = rawMemberTypeList.map((item) => { ...item });
1. 스프레드 문법([...])은 얕은 복사입니다
const newList = [...rawMemberTypeList];
- 배열 자체는 새로운 객체로 생성됩니다.
- 하지만 배열 안의 요소(객체)는 기존과 동일한 참조를 가리킵니다.
- 즉, 각 요소는 여전히 원본 배열의 객체와 연결되어 있습니다.
결과
newList[0].type = 'admin'
처럼 요소의 속성을 변경하면,rawMemberTypeList[0]
도 같이 변경됨- 객체 안의 내용이 공유되는 얕은 복사
2. map + Spread는 깊은 복사(1단계)입니다
const newList = rawMemberTypeList.map((item) => { ...item });
map()
을 통해 각 객체를 순회하면서, 내부 속성까지 복사한 새로운 객체를 만들어 배열에 넣습니다.- 배열도 새로, 객체도 새로 만들어지므로 원본과 참조가 완전히 분리됩니다.
결과
newList[0].type = 'admin'
을 해도rawMemberTypeList
는 변경되지 않음- 1단계 깊은 복사 (객체 내부에 또 다른 중첩 객체가 있다면 추가 처리가 필요)
정리: 얕은 복사 vs 깊은 복사 (1단계 기준)
방법 | 배열 구조 | 객체 참조 | 원본 영향 여부 |
---|---|---|---|
[...arr] |
새 배열 | 기존 객체 참조 | 있음 |
arr.map(item => ({ ...item })) |
새 배열 | 새 객체 | 없음 |
실무 팁
- 단순한 리스트 복사에는
[...arr]
도 괜찮지만, 객체를 포함한 배열이라면map + spread
를 추천합니다. - 중첩 객체까지 완전한 깊은 복사를 원할 경우에는
lodash.cloneDeep()
같은 유틸 함수 사용을 고려해보세요.
마무리
JavaScript에서의 복사는 단순히 =
또는 ...
로 해결되지 않습니다.
"얕은 복사 vs 깊은 복사"의 개념을 명확히 이해하고 있어야, 데이터가 예상과 다르게 변하지 않도록 방지할 수 있습니다.
728x90
'언어 · 런타임 > JavaScript' 카테고리의 다른 글
JavaScript DFS에서 [...path, i]와 push/pop 비교 - 상태 복사 vs 복원 (0) | 2025.05.08 |
---|---|
백준 JavaScript 제출법 총정리: fs, readline 입출력 예제와 주의사항 (0) | 2025.04.24 |
JavaScript란? (0) | 2024.03.05 |
[Node.js] 이벤트 디멀티플렉싱 (0) | 2024.03.05 |