JavaScript의 얕은 복사, 깊은 복사
얕은 복사와 깊은 복사에 대해 알아보자
얕은 복사
얕은 복사란, 복사본이 만들어진 원본 객체와 같은 참조¹를 공유하는 복사다.
이는 원본과 복사본이 독립적이지 않으므로, 원본이나 복사본의 중첩된 속성을 변경하였을 때 다른 객체까지 변경될 수 있다.
- 이때의 '참조(Reference)'란 객체가 저장된 메모리 위치(주소)를 가리키는 말이다.
깊은 복사
깊은 복사는 복사본이 원본 객체와 같은 참조를 공유하지 않는 복사다.
이는 원본과 복사본이 완전히 독립적이기에, 어느 한쪽을 변경하더라도 다른 객체가 변경되지 않는다.
Q1. 얕은 복사의 문제점은?
얕은 복사에서 원시값은 독립적으로 (값 자체가) 복사되는 반면, 객체나 배열은 참조가 복사되기에 원본과 복사본이 같은 참조를 공유한다. 앞서 설명한 바 있으나 이러한 상황에서 원본이나 복사본의 중첩 객체 속성을 재할당했을 경우, 자연히 다른 객체에도 영향을 주게 된다. 바로 이것을 얕은 복사의 문제점으로 볼 수 있다.
Q2. Javascript에서 '깊은 복사'를 하는 법?
참고
Javascript의 객체는 단순 값이 아니라, 메모리 안에서 서로 복잡하게 연결된 구조이기 때문에 깊은 복사를 이용하여 메모리 상의 복잡한 구조 전체를 복사하는 것이 쉽지 않다.
JSON.stringify()²를 사용하여 객체를 JSON³ 문자열로 변환하고, JSON.parse()⁴로 문자열을 다시 새로운 JavaScript 객체로 변환하여 깊은 복사를 할 수 있다.
- JSON.stringify : JSON.stringify() 메서드는 JavaScript 값이나 객체를 JSON 문자열로 변환한다.
3. JSON : JavaScript Object Notation의 약자. 데이터를 텍스트 형식으로 표현하는 방법이다.
4. JSON.parse() : JSON.parse() 메서드는 JSON 문자열의 구문을 분석하고, 그 결과에서 JavaScript 값이나 객체를 생성한다.
const ingredientsList = ["noodles", { list: ["eggs", "flour", "water"] }]; const ingredientsListDeepCopy = JSON.parse(JSON.stringify(ingredientsList));
이해를 위한 정리 (클릭해서 펼치기)
첫째 줄 : 원본 배열 (문자열 "noodeles"과 객체 안에 배열이 있는 {list: [...]}
둘째 줄 : JSON.stringify(...)로 배열을 JSON 형식의 문자열로 변환, JSON.parse(...)로 그 문자열을 다시 객체/배열로 변환
다만 이와 같은 오래된 방식은 1) 함수나 심볼 등을 복사할 수 없고, 2) undefined도 복사되지 않고 사라지며, 3) Date 객체 등은 문자열로 변환되는 등의 문제가 있다. 따라서 직렬화할 수 없는 JavaScript 객체에 이를 적용할 수는 없다.
현재 가장 많이 사용되고 있는 방법은 structuredClone() 메서드를 사용한 방식이다.
structuredClone(value) structuredClone(value, options)
Q3. 프론트엔드(브라우저)와 서버 간의 통신에서 JSON이 사용되고 직렬화와 역직렬화가 사용되는 이유는?
브라우저와 서버의 환경은 서로 다르기에 객체 자체를 직접 보낼 수 없으므로, JSON 같은 문자열 형식으로 변환해야 한다. 이때, 직렬화는 객체를 JSON 문자열로 바꿔 네트워크로 전송하기 위한 과정이며 역직렬화는 전달받은 JSON 문자열을 다시 객체로 복원해 사용하기 위한 과정이다.
댓글
댓글을 작성하려면 이 필요합니다.