React 의 불변성에 대해 (React의 규칙)

yiwoojung·2024년 7월 6일
0

React

목록 보기
9/9
post-custom-banner

불변성 (Immutable)이란?

불변성이라는 건 값이나 상태를 변경할 수 없다는 것을 의미한다.
= readonly, 읽기 전용이라고 생각하자.



리액트의 state는 JavaScript 값을 보유할 수 있다.

const [x, setX] = useState(0);
setX(5);

x state가 0에서 5로 변경되었지만 숫자 자체는 변경되지 않았다.

그렇다면 객체는 어떨까?

const [position, setPosition] = useState({ x: 0, y: 0 });
position.x = 5;

이런식으로 객체 자체의 내용을 변경하는 것은 가능하다.

하지만 React state 객체는 Number, Boolean, String 과 같이 불변인 것처럼 취급해야 한다.

객체나 배열과 같은 참조 타입의 상태는 직접 mutate하는 대신 항상 replace 해야 한다.
즉, 배열 내부에 항목을 다시 할당하거나 배열을 변형하는 메서드를 사용해서는 안된다.

이렇게 외부에 존재하는 원본 데이터를 직접 수정하지 않고, 원본 데이터의 복사본을 만들어서 값을 사용하며 불변성을 지켜줌으로써 side-effect도 방지할 수 있다.


리액트는 상태값을 업데이트 할 때 객체의 속성 하나하나를 비교하는게 아니라 참조값만 비교해서 상태 변화를 감지(얕은 비교)하기 때문이다.

따라서 Object 나 Array 의 원본 속성이나 값을 직접 바꾸게 되면 React에서 상태가 바뀌었다고 파악하지 못하기 때문에 불변성을 지키는 업데이트가 필요하다.

이렇게 얕은 비교를 통해 새로운 값이라고 판단되어 부모 컴포넌트가 re-rendering 하게 되면, 자식 컴포넌트도 함께 re-rendering 된다.

혹은 props이 객체, 배열 또는 함수인 경우 컴포넌트가 re-rendering 된다.

이런 방지하기 위해서 props를 단순화 하거나 부모 컴포넌트에서 props를 memoization 해서 성능을 최적화할 수 있다.
reactjs | memo - React


어떻게 불변하게 만들 수 있을까?

  1. spread 연산자를 사용한다.
    • 1레벨 깊이에서는 스프레드 문법을 사용해서 객체를 얕은 복사하면 객체 주소가 달라지기 때문에 불변성을 유지할 수 있다.
    • 중첩 객체 같은 경우는 불변성을 유지할 수 없다.
  2. Object.assign 메서드를 활용한다.
    • 얕은 복사를 가능하게 해준다.
    • 반복문 없이도 간단하게 객체를 복사할 수 있다.
  3. Immer.js 와 같은 불변성 관리 라이브러리를 사용한다.
  4. lodash의 _.cloneDeep() 과 같은 깊은 복사를 지원하는 라이브러리 사용한다.
  5. 배열에서는 push , splice 등의 원본데이터를 변경하는 메서드를 사용하지 말고, concatfiltermap , slice 등을 사용한다.

그렇다면 state 변형이 권장되지 않는 이유는 무엇일까?

이 부분도 자세히 나와있어서 가져왔다.

reactjs | Updating Objects in State - React

결론적으로 디버깅을 쉽게하고, 어플리케이션을 최적화하며, 더 간단하게 구현하기 위해 state를 변형하는 것이 권장되지 않는다고 한다.


React의 불변성 정리

  • React의 모든 state를 변경 불가능한 것으로 취급한다.
  • 객체/배열을 state에 저장하는 경우 객체를 변형해도 렌더링이 트리거되지 않고 이전 렌더링 "스냅샷"의 상태가 변경된다.
  • 객체/배열를 변형하는 대신, 새로운 버전을 만들고, 해당 객체/배열에 상태를 설정하여 다시 렌더링을 트리거한다.
  • spread 연산자를 사용하면 객체/배열의 사본을 만들 수 있다.
    • 얕은 복사를 하기 때문에 1 레벨 깊이까지만 복사한다.
  • 중첩된 객체/배열를 업데이트하려면 업데이트하는 위치부터 위쪽까지 복사본을 만들어야 한다.
  • 필터링되거나 변환된 항목으로 새로운 배열을 만들려면 filter, map , slice 를 사용하자.
    • push , splice 등의 원본데이터를 변경하는 함수를 사용하지 말자.
  • 반복적인 코드 복사를 줄이려면 Immer를 사용할 수 있다.


참고

profile
의견이 있으시거나 잘못된 내용을 발견하셨다면 재빨리 댓글 주세요 。•◡•。
post-custom-banner

0개의 댓글