개발하는SM

[React] React 의 참조형 타입 State 관리와 Javascript 깊은 복사 본문

Web/Front-End

[React] React 의 참조형 타입 State 관리와 Javascript 깊은 복사

개발하는SM 2023. 3. 19. 12:17

서론

React에서 참조형 타입( 배열, 객체 )의 State를 관리하다 보면, 이전 State의 값을 안전하게 복사해오는 방법에 대해 고민하게 된다.

그 때마다 Javascript 의 Shallow Copy 와 Deep Copy 에 대해 항상 검색하게 되는데, 

이런 내용에 대해 확실하게 정리하고 넘어가려고 한다.


원시값과 참조값

원시 값

자바스크립트 원시 값

원시값에는 위와 같이 7가지 종류가 있고, 원시값은 변형할 수 없다.

원시 자료형을 변수에 할당할 때는 변수에 값을 저장한다. ( 값에 의한 전달 )

기존 변수 ( a ) 를 복사해서 다른 변수 ( copiedA ) 에 할당해 준 다음, 다른 변수 ( copiedA ) 를 변경해도 기존 변수 ( a ) 에는 영향을 주지 않는다.

원시형 변수 복사

참조값

원시값이 아닌 것들은 모두 참조형이다. ( 객체, 배열, 함수 등 )

참조 자료형을 변수에 할당할 때는 값이 아닌 주소를 저장한다. ( 참조에 의한 전달 )

아래는 참조 자료형인 배열을 복사하여 변경하는 예시이다.

기존 배열 변수 ( arr ) 을 복사하여 새로운 배열 변수 ( copiedArr ) 에 할당해준 다음,

새로운 배열 변수 ( copiedArr ) 에만 4 값을 추가로 넣어주었음에도 기존 배열 변수 ( arr ) 값이 함께 변경된 것을 확인할 수 있다.

참조형 변수의 복사와 변경


JavaScript 의 깊은 복사와 얕은 복사

위의 참조형 변수와 같은 예시가 얕은 복사이다.

자바스크립트의 참조형 변수의 경우 = 을 통해 단순히 값을 할당하게 될 경우 얕은 복사가 일어나게 되며,

이는 결국 하나의 데이터를 공유하는 형태이다.

이러한 현상은 React 에서 참조형 변수값의 State 를 관리할 때, 우리가 의도한 것과 다른 방식으로 프로그램이 흘러갈 수 있게 만든다.

따라서 JavaScript 의 깊은 복사를 활용해야 한다.

JavaScript 참조형의 깊은 복사

가장 간단하게 참조형의 깊은 복사를 하는 방법은, Spread Operator ( ... ) 를 활용하는 방법이다.

Spread Operator 는 간단히 말해 객체 또는 배열의 값을 추출해내는 연산자라고 생각하면 된다.

아래 예시를 보면, 기존 배열 변수 ( arr ) 를 새로운 배열 변수 ( copiedArr ) 에 할당해 줄 때 Spread Operator 를 활용하여 배열의 값을 추출하여 할당해주었다.

그 결과, 새로운 배열 변수 ( copiedArr ) 에 4라는 값을 넣어도 기존 배열 변수 ( arr ) 는 변경되지 않음을 확인할 수 있다.

두 개의 변수 ( arr, copiedArr ) 가 서로 다른 참조값 ( 주소값 ) 을 가지고 있는 것이다.

Spread Operator 를 활용한 깊은 복사

이렇게 Spread Operator 를 활용하면 간단하게 참조형 변수의 깊은 복사를 할 수 있지만,

Spread Operator 의 경우 두 단계 이상의 depth 부터는 깊은 복사를 해 주지 않는다..!

아래 예시를 보자.

person 이라는 새로운 객체를 생성했고, person 객체 내부에는 skillset 이라는 객체가 추가로 존재한다.

새로운 객체 copiedPerson 을 만들고 Spread Operator 를 사용하여 person 값을 복사해준 다음, 

copiedPerson 의 skillset 값을 변경한 경우 기존 person 의 skillset 값까지 변경되어 버린다.

Spread Operator 의 Copy 방식은 1단계 depth 까지만..

그러므로, 2단계 이상의 객체를 깊은 복사 해주어야 할 경우 다른 방식을 사용해야 한다.

완벽한 깊은 복사가 필요한 경우 lodash 의 cloneDeep 라이브러리를 활용하는 것이 가장 효율적이다.


참조

JS-깊은복사와-얕은복사-그리고-spread-operator에-대해서