React는 불변성을 지켜야 한다? 지켜야 하는 이유?

Mincho·2023년 7월 26일
0

React

목록 보기
11/15
post-thumbnail

함수형? 불변성?

  react에서 hook을 도입한 이래로 js라이브러리로는 강력한 1대장 역할을 하고 있습니다. hook을 도입하여 기존에 class형 컴포넌트에서 prototype 언어인 js에 맞게 function 컴포넌트의 시대가 도래하였는데요.

 함수형을 강조하는 만큼 js에서의 함수는 일급객체로 불리우고 있는데,그로 인해 함수를 사용할 때 부수효과가 일어나지 않게 순수하게 작동해야 합니다. 이것은 저희가 알아볼 불변성과의 연관관계가 있습니다.



기본적인 js 메모리 구조에 대해서

 자바스크립트의 경우 메모리는 스택과 힙으로 구성되어 있습니다.힙은 참조값 즉 객체가, 스택같은 경우는 원시값이 저장됩니다. JS기초지식이므로 간단하게 보고 넘어가겠습니다.

원시 타입 : Boolean, String, Number, null, undefined, Symbol
참조 타입 : Object, Array

 원시값의 경우 값자체가 readOnly값으로 변수값이 그대로 스택에 저장되는 반면, 객체같은 참조 타입은 힙에 값이 저장되지만 이 값을 참조하는 메모리 주소는 스택에 저장됩니다.

let a = "hello"
let b = a

console.log(a, b) // "hello" , "hello"

b = "hi"
console.log(a, b) // "hello", "hi!"

 다음과 같이 원시값을 복사해서 복사한 값을 변경해도 변하지 않습니다. 이 것을 불변성입니다. 하지만 참조값은 다른 결과가 나타나는데요.

let a = {data : "hello"}
let b = a

console.log(a, b) // {data : "hello"}, {data : "hello"}

b.data = "hi!"

console.log(a, b) // {data: 'hi!'}, {data: 'hi!'}

 위와 같이 복사한 b의 값을 변경 했을 뿐인데 a의 본래 값까지 변경되는데요. 객체 자체 값을 가지고 있는게 아니라 객체의 주소값을 공유하고 있다고 보면됩니다. 이것을 얕은 복사라고 합니다. 추가적으로 js는 GC(가비지 콜렉터)가 지원되기 때문에 메모리 누수에 대한 문제는 해결됩니다.


React에서 불변성

 React에서는 상태 관리를 할 때 얕은 참조 비교를 통해서 이루어집니다. 즉 메모리의 주소 값만을 가지고 비교를 합니다.

  위의 그림을 보게 되면 모든 변경 사항들을 공유하고 있는데요. 기존 값을 그대로 두는 것이 아니라 변경하면서 하는 형태 앞서 살펴봤던 객체 타입에서 볼수 있던 것입니다. 이것은 불변성의 법칙에서 어긋나는 것입니다. 만약 참조값이 변경되더라도 감지가 되지않습니다. 왜냐하면 같은 주소를 참조하고 있기 때문입니다.

 초기 상태에서 기존에 있던 값을 변경하지 않고 그대로 두고 새로운 객체를 만들어 저장하는 원리입니다. 이렇게 값을 비교하게 되면 React에서는 다른 주소를 가진 값을 비교하게 되고 결과적으로 이 것을 반영하게 되는 것입니다.

단방향 흐름으로 상태를 관리를 하는 Redux 공식 홈페이지에서도 불변성을 강조하고 있습니다.



그렇다면 불변성이 필요한 이유는??

상태의 흐름파악

 현재 가장 많이 사용되고 있는 Redux또한 이 불변성을 이용해서 기존 객체를 변경하지 않고 새로 생성하며 상태를 관리합니다. redux devtools를 이용하며 이 모든 객체를 확인하며 변경사항 까지 관리하며 디버깅이 가능합니다.

위의 devtool을 활용하면 상태관리 현 상태를 원활하게 확인할 수 있습니다.

리렌더링 방지

 리엑트에서 리렌더링 조건 중 하나는 부모 컴포넌트가 리렌더링 되면 자식 컴포넌트들은 어떤 상태던간에 같이 리렌더링이 일어납니다. 이러한 리렌더링 방식은 웹 어플리케이션 성능에 영향을 미치기 때문에 최적화가 필요합니다. 이를 위한 해결방안으로 React에서는 memo를 사용합니다. 이 memo의 방식 또한 값의 변경을 감지하는데 이것 또한 기존의 객체 상태를 비교하는 방식이면 감지를 못하기 때문에 불변성을 유지하는 것 입니다.

memo는 자식 컴포넌트를 메모이징하여 변경된 값이 없다면 부모컴포넌트가 변경된다 해도 리렌더링이 되지 않습니다.


Reference
https://ko.redux.js.org/usage/structuring-reducers/prerequisite-concepts/#%EB%B6%88%EB%B3%80%EC%84%B1-%EC%82%AC%EC%9D%B4%EB%93%9C%EC%9D%B4%ED%8E%99%ED%8A%B8-%EB%B3%80%ED%99%94%EC%97%90-%EB%8C%80%ED%95%9C-%EC%A3%BC%EC%9D%98
https://hsp0418.tistory.com/171
https://narup.tistory.com/268

👍올바른 피드백은 언제든지 환영입니다~!

profile
사진찍는 개발자.

1개의 댓글

comment-user-thumbnail
2023년 7월 26일

좋은 정보 얻어갑니다, 감사합니다.

답글 달기