| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- rest operator
- codility
- DB Navigator
- react
- 섬 연결하기
- useState
- 프로그래머스
- State
- Kruskal Algorithm
- Segment Tree
- batch udpate
- useContext
- BOJ2042
- java
- 객체지향 설계 5원칙
- React 훅 사용규칙
- 리액트 상태값 업데이트
- state update scheduling
- spread operator
- heap
- DFS
- JS Array Functions
- Modern Javascript
- 리액트의 작동방식
- useReducer
- Lifting State Up
- MST구현
- Greedy
- 프로그래머스#JAVA
- 리액트 성능 최적화
- Today
- Total
개발하는SM
[React] React 의 참조형 타입 State 관리와 Javascript 깊은 복사 본문
서론
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 의 경우 두 단계 이상의 depth 부터는 깊은 복사를 해 주지 않는다..!
아래 예시를 보자.
person 이라는 새로운 객체를 생성했고, person 객체 내부에는 skillset 이라는 객체가 추가로 존재한다.
새로운 객체 copiedPerson 을 만들고 Spread Operator 를 사용하여 person 값을 복사해준 다음,
copiedPerson 의 skillset 값을 변경한 경우 기존 person 의 skillset 값까지 변경되어 버린다.

그러므로, 2단계 이상의 객체를 깊은 복사 해주어야 할 경우 다른 방식을 사용해야 한다.
완벽한 깊은 복사가 필요한 경우 lodash 의 cloneDeep 라이브러리를 활용하는 것이 가장 효율적이다.
참조
'Web > Front-End' 카테고리의 다른 글
| [Javascript] 자바스크립트의 동작방식 - 싱글스레드와 비동기 (0) | 2023.03.25 |
|---|---|
| [React] Context API 와 useContext Hook (0) | 2023.03.20 |
| [React] Hook 사용규칙 (0) | 2023.03.13 |
| useState() VS useReducer() (0) | 2023.02.20 |
| React useEffect ( + Cleanup 함수 ) (0) | 2023.02.19 |