[JavaScript]Object.assign()(shallow copy or deep copy)

홍헌·2023년 12월 27일
0

JavaScript

목록 보기
1/2

Object.assign() 기능

요즘 현재 진행하는 프로젝트 중에 시간이 좀 남으면 다른 파트 코드를 틈틈히 뜯어 보고 있다. 이전 프로젝트도 그렇고 현재 프로젝트도 Object.freeze, Object.assign을 많이 사용하길래 그냥 이런 거구나 하고 넘어갔다. 그러던 중

const returnedTarget = Object.assign({}, source);

이와 같이 객체를 넣어주는 경우가 있었다.

잠깐 여담이지만 Object.assign은 target 객체에 원하는 source 객체를 반영해준다. 예를 들어

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

Object.assign(target, source)

이렇게 된다면 target의 값은 { a: 1, b: 4, c: 5 } 이렇게 변한다는 얘기다. 아래는 실제로 코드를 돌려본 값이다.

Object.assign()는 deep copy가 되나?

다시 돌아와서,

const returnedTarget = Object.assign({}, source);

이런 식으로 넣어준다면 어떻게 될까? 그냥 returnedTarget에 source와 동일한 값을 대입해 주는 것이다. 난 이 코드를 보고 '왜 굳이 이렇게 할까? 혹시 deep copy가 가능한가?'라는 생각을 했다. 만약에 값을 그대로 대입해주고 싶었던 것이면 spread로 해서 값을 복사해주면 되는데 굳이 길게 썼다면 deep copy가 되지 않을까 했다. (참고로, spread도 deep copy는 되지 않는다. 혹시 shallow copy, deep copy 모르시는 분들이 계신다면 아래 참고.) 그래서 궁금하면 돌려보는 게 제일 빠르니까 돌려봤다.

위 사진을 보면 알 수 있겠지만 아니었다. Object.Assign도 shallowCopy만 가능했다. 그래서 작성하신 분의 코드를 더 읽어보니 Axios로 데이터를 받아오고

target = Object.Assign({},data.body) 

이런 식으로 작성하고 계셨다. 결국 그냥 그 분이 이렇게 코드 짜는 걸 좋아하시는 거 같다. 그럼에도 그냥 어차피 찾아본 거 '이런 식으로도 복사하는 방법이 있구나. 하는 김에 shallowCopy랑 deepCopy도 다시 한 번 정리하자' 라는 마음으로 작성했다.

결론

Object.assign({}, source); 

으로도 복사된다. 근데 굳이?

참고. shallow copy & deep copy

const target = { a: 1, b: 2 };
const targetCopy = target;

JavaScript를 처음 접하고 원본을 보관해야해서 카피한 데이터를 조작해야한다 거나 아님 또 다른 이유로 데이터를 복사해 놓으려다 위와 같은 실수에 당황한 경험이 있을 거다. 그리고 그냥 무작정 spread를 이용해서 넣으면 된다는 글들을 보고 따라쳐서 해결한 경험이 있을 것이다.(필자는 첨에 그랬었다.)

그런데 왜 굳이 spread를 사용할까? 그 이유는 JavaScript에서 객체를 변수에 할당할 때, 객체의 참조(reference)가 변수에 저장되기 때문이다. 이 뜻은 객체가 가진 값들 각각을 저장하는 것이 아니라, 객체의 주소를 가지고 있어서 targetCopy에

{ a: 1, b: 2 }; 

이 객체의 주소를 저장하는 것이기 때문에 스프레드 연산자를 사용하여 복제하고 이것이 shallow copy이다. 근데 여기서 발생하는 문제가 있다.

const target = { a: 1, b: {e:2} };
const targetCopy = {...target};

targetCopy.a=10;
targetCopy.b.e=10;

이렇게 되면 어떻게 될까? 먼저 얘기하면 a는 각각 값을 가지지만, e는 동일한 값을 갖게 된다.

왜 그런지는 간단하다. 위에서 설명한 거 같이 b는 참조가 변수에 저장되었기 때문이다. 이런 문제를 해결하는 간단한 방법은

 JSON.parse(JSON.stringify(target));

를 하는 것이다. 이는 target을 문자열로 변환하고, 다시 객체로 변환하면서 새로운 객체가 되는 것이기 때문에 값이 복제가 되며 이러한 복제를 deep copy라고 한다.

물론 위와 같은 방식만 있는 것은 아니며 lodash같은 라이브러리를 사용하는 방법도 있다.

0개의 댓글

관련 채용 정보