React에서의 Immutability

BirdsOnTree·2022년 10월 15일
1

React

목록 보기
7/10
post-thumbnail
post-custom-banner

React에서의 불변성

JS에서...

애초에 원시 타입의 값들은 불변성을 가지고 있지만 참조형 값들( 객체, 배열, 함수 등)은 원시 타입과는 다르게 동작한다.

const Obj = {
  word: 'apple'
}

Obj.word = 'banana'

number가 참조하고 있는 apple의 주소 값은 변경된다.

복사가 이루어지는 것이 아닌 참조값을 갖게되기 때문에 사본을 수정하게 되면 원본도 수정이 되어버린다.


let string = 'data1' // 1. string: 'data1'가 메모리 영역1에 등록됩니다. 
string = 'data2' // 2. string: 'data2'가 메모리 영역2에 등록됩니다.

string 변수는 'data1' → 'data2' 로 값이 변경된 것처럼 보이지만 실제 메모리영역에는 'data1', 'data2' 둘다 존재하게 된다.
즉, 메모리영역에서 'data2'는 'data1'을 대체하는 것이 아니라 새로운 영역에 할당된다.

let array = [1, 2, 3, 4] // 메모리영역 1
array.push(5) // 메모리영역 1 

array = [1, 2, 3, 4] // 메모리영역 2 (새로운 참조값)

array.push(5)는 원본데이터를 수정함으로써 불변성을 지켜주지 않은 것이되고, array = [1, 2, 3, 4] 는 새로운 배열 [1, 2, 3, 4]을 할당하고 새로운 참조값을 만들어주어 불변성을 지켜준 것이다.

불변성의 진짜 의미는 메모리 영역에서 값을 변경할 수 없다는 의미이다.


React에서도...

리액트에서 불변성을 지켜주는 이유는 리액트가 상태 업데이트를 하는 원리 때문이다.
리액트는 상태값을 업데이트 할 때 얕은 비교를 수행한다. 즉 객체의 속성 하나하나를 비교하는게 아니라 참조값만 비교하여 상태 변화를 감지하게 된다. 이런 이유로 배열이나 객체를 업데이트 할때 setState를 사용해서 setState([...state, newState]), setState({...state, [key]: value}) 이런식으로 배열이나 객체를 새로 생성해서 새로운 참조값을 만들어서 상태를 업데이트 해야하고, 업데이트 하는 과정에서 기존의 객체의 값을 직접적으로 수정하면 안된다. 이런 행위가 불변성을 지켜주는 것이다.

불변성을 지켜줌으로써 얻게 되는 또 다른 이점은 바로 사이드 이펙트를 방지하는 것이다.
외부에 존재하는 원본데이터를 직접 수정하지 않고, 원본데이터의 복사본을 만들어서 값을 사용하기에 예상치 못한 오류를 사전에 방지할 수 있다.
만약 다른 어떤 곳에서 원본데이터를 사용하고 있다고 하면 어플리케이션 어딘가에서 사이드 이펙트가 일어날 가능성이 있기 때문이다.

결국 리액트는 불변성을 지킴으로 인해 효과적인 상태 업데이트와 사이드 이펙트를 방지하는 이점들을 얻고 있다.

또한 기본적으로 setState 를 통하여 state 를 변경하지 않으면 리렌더링이 되지 않는다. 또한 불변함을 유지 않으면 왜 컴포넌트 최적화가 힘들어질수가 있다.

리액트의 기본 속성으로 부모 컴포넌트가 리렌더링 되면, 자식 컴포넌트들 또한 리렌더링이 된다. 이 과정은 가상 DOM 에만 이뤄지는 렌더링이며, 렝더링을 마치면 리액트의 diffing 알고리즘을 통해서 변화가 일어나는 실제 부분만 업데이트를 해주게 된다.
다시말해 React에서 값이 변한지 모르게 된다.

물론 새로운 객체를 만들어서 기존의 객체는 건들이지 않으면서도 불변성을 유지하면서 값을 업데이트 할 수 있지만, state의 구조가 복잡할수록 실수가 발생할수도 있다.

불변성을 지키기 위해서

spread operator, map, filter, slice, reduce 등등 새로운 배열을 반환하는 메소드들을 활용하면 된다.

setState를 이용할 때 원시타입 경우에는 값을 바로 넣어주어도 되지만
참조타입인 경우에는 새로운 객체나 배열을 생성한 후 값을 넣어주어야 한다.

다른 방법으로는 Immutable.js 이 있다.


Immutable.js

최근 들어서는 Immutable에 대한 글이 별로 없는것 같다.
아마도 ES6, Immer 때문이 아닐까 라는 생각을 하며 Immer에 대한 공부를 더 해봐야 겠다는 생각을 하였다
하지만 React에서의 불변성에 대해서 공부하는 과정에서 Redux와 함께 사용하면 좋은 기능이라고 해서 함께 알아보았다.

yarn add immutable

Immutable 을 사용 할 때는 다음 규칙들이 있다.
객체는 Map
배열은 List
설정할땐 set
읽을땐 get
읽은다음에 설정 할 땐 update
내부에 있는걸 ~ 할땐 뒤에 In 을 붙인다: setIn, getIn, updateIn
일반 자바스크립트 객체로 변환 할 땐 toJS
List 엔 배열 내장함수와 비슷한 함수들이 있다 – push, slice, filter, sort, concat… 전부 불변함을 유지함
특정 key 를 지울때 (혹은 List 에서 원소를 지울 때) delete 사용
프로젝트의 엔트리인 index.js 에서 시험삼아 Immutable 을 불러오고, Map 과 List 를 사용해보세요.

참조
[꿀로그]
https://hsp0418.tistory.com/171
[구보현 블로그]
https://bohyeon-n.github.io/deploy/react/react_immutable.html

post-custom-banner

0개의 댓글