티스토리 뷰

내부 프로젝트로 Testcase를 자동으로 정리해주는 프로젝트를 진행하게 됐다.

 

백엔드에서 서비스로직만 처리할 게 아니라, 화면을 추가로 그려야했기 때문에 자연스럽게 자바스크립트를 보게 됐고... 너무 많은 이슈들을 마주쳤다.(별로 언급하고 싶지 않은 이유로 발생한 것들이다...)

 

그 중 하나가 Object의 깊은 복사(Deep Copy) / 얕은 복사(Shallow Copy) 이슈였고, 이거 때문에 몇 시간을 끌었다.

어떤 문제 였나?

결론부터 이야기하자면, 나는 깊은 복사가 하고 싶었다. 그런데 배열 안의 오브젝트의 처리에 문제가 있었다.

Java에서의 배열(Array) 모두 같은 자료형만을 취급한다. 하지만 Javascript의 Array는 제한 없이 사용할 수 있다.

a = [ 'abc', { a : 'ab' , b : 'bc'} , 111]

위와 같은 형태로 저장이 가능하다. 여기서 내가 하고싶었던 것은 a의 형태는 유지하고 새로운 배열에 a 배열을 그대로 저장한 후, 내부의 a,b 키를 갖는 object를 수정하고 싶었다.

 

여기서 일반적으로 사용하는 깊은 복사들이 정상적으로 동작하지 않았다. 해봤던 몇 가지만 정리해 봤다.

 

1. 깊은 복사라 사용되지만 안됐던 것

  • spread 연산자
c = [...a]
c[1].c = 'ccc'
  • map으로 object 복사
c = a.map(e=>e)
c[1].c = 'ccc'

안됨

 

위 방법들은 모두 1 depth만 깊은 복사되어 변경이 가능했지만, 2 depth의 object들은 모두 얕은 복사로 동작한다.(c[1]의 object 변경 시 a도 변경 됨)

 

2. 깊은 복사 중에서 되는 것

  • JSON 변환 후 사용
b = JSON.parse(JSON.stringify(a))

(사실 여기 예제에서는 정상적으로 동작했지만, 내가 사용했던 자료구조 내에선 어떤 이유에선지 JSON 변환도 잘 동작하지 않았었다.)

  • structuredClone() 사용
b = structuredClone(a)

이것 저것 알아보다가 structuredClone()을 사용했다. 별다른 이유는 없고, 가장 직관적이라 사용했다.

무식한 방법이지만, b = []를 선언한 후 forEach를 돌리면서 하나씩 저장하는 방식이 가장 확실하게 저장하는 방식이다...

마치며

사실 JAVA와 같은 클래스 기반의 객체 지향 프로그래밍 언어에서는 사실상 잘 발생하지 않는 이슈이다. 깊은 복사/얕은 복사의 개념을 알고 있으면 A = B;와 같은 객체 복사는 하지 않을 것이 기 때문이다.

 

참 Javascript의 Object가 편한거 같으면서도 이슈를 발생시키는 원인이 되는 것 같다. 자유도가 높은만큼 잘 쓰기 어려운 것 같다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함