본문 바로가기
Web development/Node.js & Typescript

[Javascript] 객체 수정시 원본이 변경되는 문제(얕은 복사와 깊은 복사)

by 자몬다 2021. 5. 6.

자바스크립트의 값의 종류는 원시값과 참조값이 존재한다.

Boolean, String, number, null, undefined : 원시값

Object, Array : 참조값

 

원시값의 경우 새로운 변수에 할당시 값 자체가 할당되고,

참조값은 값의 주소가 할당된다.

 

그러므로 새로운 변수에 할당 후 수정하면, 객체나 배열의 경우 원본의 값이 변경되어버린다.

const obj = {'a': 1, 'b': 2};
const tempObj = obj;

tempObj.a = 3;
console.log(obj); // {'a': 3, 'b': 2}

 


문제

문제는, formData의 변경이 필요할때 등 원본을 보존하는 복사가 필요한 경우가 생긴다.

 

예를 들면, 아래와 같은 form 데이터가 있다.

formData = {
    name: 'effy',
    isDeleted: '0',
    profileImage: File
}

isDeleted input은 string 0, 1로 들어오는데, submit시에는 boolean으로 변환해주어야 한다고 가정하자.

formData.isDeleted = false;

이렇게 해버리면 fromData의 원본 객체가 변경되어 버리는데, 

submit에 실패하거나, 추가로 수정하는 경우 input값이 꼬여버릴 것이므로, 원본 객체를 변경하지 않고 새로운 변수에 할당하여 데이터를 수정해야 한다.

 

그러나 아래와 같이 할당하는 경우, 얕은 복사가 되어 tempFormData를 수정하더라도 formData가 수정된다.

const tempFormData = formData;
tempFormData.isDeleted = false;

console.log(formData.isDeleted); // false

 

해결방법

아래와 같은 꼼수를 사용하면 깊은 복사가 일어난다.

const tempFormData = JSON.parse(JSON.stringify(formData));

가장 간단한 방법이지만 성능상으로는 별로 좋지 않다고 하니 필요시 다른 방법을 사용해야 한다.

lodash사용, 객체를 재귀함수로 복제하는 방법이 있다.

 

주의사항

추가로 주의사항이 있는데, File같은 경우 JSON.parse(JSON.stringify())하면 형태가 변경되어 버리므로,

tempFormData.profileImage = formData.profileImage

위와 같이 복사된 객체에 다시 할당해주는 것이 좋다.

 

th0566님의 글을 참고하여 작성하였습니다.

링크 : https://velog.io/@th0566/Javascript-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%AC-%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%AC

댓글