[Front-end] 개발자 공부

[개발 공부 73일차] React에서 State 변형을 권장하지 않는 이유 5가지

MOLLY_ 2024. 6. 18. 21:54
728x90

< 목차 >
1. Immer
2. React에서 State 변형을 권장하지 않는 이유 5가지
3. State의 배열 업데이트하는 법
4. 금일 소감

 

 

오늘은 Study 때 내가 맡지 않았던 React 공식 문서 파트를 읽었다. 약간 밀렸어서 직전 스터디까지의 분량을 후루룩 읽었다. 새롭게 알게 된 부분과 궁금했던 부분에 대한 호기심이 풀려서 그 내용을 위주로 작성해 보려 한다!

 

 

1. Immer

 

: React에서 불변성(immutable state)을 관리하기 위한 라이브러리

Immer는 상태 업데이트 로직을 간단하고 읽기 쉬운 방식으로 작성할 수 있도록 해, 복잡한 객체의 불변 업데이트를 간단한 방법으로 처리할 수 있다. 기본적인 useState 훅과 유사하게 작동하며, 상태를 불변성을 유지하면서 업데이트할 수 있도록 도와준다.

 

State를 복사할 때, 반복적인 코드 복사를 줄이려면 Immer를 사용하는 게 좋다.

 

 

사용법

  1. useImmerimport 한다.
  2. 초기 상태를 설정하여 useImmer를 호출한다.
  3. 상태를 업데이트할 때는 제공되는 업데이트 함수를 사용하여 직접 변경한다.

 

 

예시 코드

import { useImmer } from "use-immer";

function App() {
  const [state, updateState] = useImmer({ count: 0 });

  function increment() {
    updateState(draft => {
      draft.count += 1;
    });
  }

  return (
    <div>
      <p>{state.count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

 

이 코드에서 useImmer는 초기 상태 { count: 0 } 를 받고, increment 함수 내에서 상태를 직접 변경한다. 이 방법으로 상태 업데이트 시, 불변성을 유지할 수 있다.

 

 

 

2. React에서 State 변형을 권장하지 않는 이유 5가지

왜 State를 변형하지 말라고 하는 거냐옹

 

State를 변형하지 말란 건 알겠는데,

그렇다면 대체 '왜' React에서 State를 변형하지 말라고 하는지 궁금할 수 있다. React는 다음의 5가지 이유로 State를 변형하지 말 것을 주장했다.

 

  1. 디버깅: console.log를 사용하고 상태를 변경하지 않으면 과거 로그가 최근 상태 변경으로 인해 방해받지 않는다. 따라서 렌더링 간에 상태가 어떻게 변경되었는지 명확하게 확인할 수 있다.

  2. 최적화: 일반적인 React 최적화 전략은 이전 프로퍼티나 state가 다음 프로퍼티와 동일한 경우 작업을 건너뛰는 것에 의존한다. state를 변경하지 않는다면 변경이 있었는지 확인하는 것이 매우 빠르다. 만약 prevObj === obj라면, 내부에 변경된 것이 없다는 것을 확신할 수 있다.

  3. 새로운 기능: React가 개발 중인 새로운 React 기능은 State를 스냅샷처럼 취급하는 데 의존한다. 이전 버전의 State를 변경하는 경우 새로운 기능을 사용하지 못할 수 있다.

  4. 요구사항 변경: 실행 취소/다시 실행 구현, 변경 내역 표시, 사용자가 양식을 이전 값으로 재설정할 수 있도록 하는 등의 일부 애플리케이션 기능은 아무것도 변경되지 않은 상태일 때 더 쉽게 수행할 수 있다. 과거의 상태 복사본을 메모리에 보관했다가 필요할 때 재사용할 수 있기 때문이다. 변경 접근 방식으로 시작하면 나중에 이와 같은 기능을 추가하기 어려울 수 있다.

  5. 더 간단한 구현: React는 mutation(변형)에 의존하지 않기 때문에 객체에 특별한 작업을 할 필요가 없다. 많은 "반응형" 솔루션처럼 프로퍼티를 가로채거나, 항상 프록시로 래핑하거나, 초기화 시 다른 작업을 할 필요가 없다. 이것이 바로 React가 추가적인 성능이나 정확성의 함정 없이 아무리 큰 객체라도 상태에 넣을 수 있는 이유이기도 하다.

 

 

 

 

그니까.. React의 내부 설계가 State 변형에 따라

동작하게 돼있다는 거지?

State를 변형하면 최적화와 React의 새 기능을 사용하는 데 문제가 생길 수 있단 거고?

State가 원본 그대로면 메모리에 보관했다가 필요할 때 재사용하고?

 

아~ 완벽히 이해했어

 

 


[Reference]

 

 

3. State의 배열 업데이트하는 법

자바스크립트에서의 배열은 객체의 또 다른 종류일 뿐이다.

하지만, React에서의 모든 State는 '읽기 전용'으로 취급한다. 재할당, 변형시키는 메서드는 사용 불가하다.

 

 

React State에 배열을 다룰 때는 왼쪽 열의 메서드를 지양하고, 오른쪽 열의 메서드만을 사용해야 한다.

 

 

또는 두 열의 메서드를 모두 사용할 수 있는 Immer를 사용할 수도 있다.

백그라운드에서 Immer는 항상 사용자가 초안에 적용한 변경 사항에 따라 다음 상태를 처음부터 다시 구성한다. 따라서 상태를 변경하지 않고도 이벤트 핸들러를 매우 간결하게 유지할 수 있다.

 

 

reverse

: 배열의 요소 순서를 반대로 뒤집음

 

이 메서드는 원본 배열 자체를 수정하며, 변경된 배열을 반환한다. 별도의 인자는 필요하지 않다.

예를 들어, [1, 2, 3] 배열에 reverse()를 적용하면 [3, 2, 1]로 변하고, 이 배열이 반환된다.

 

 

예시

let myArray = [1, 2, 3];
myArray.reverse();

console.log(myArray);  // 출력: [3, 2, 1]

 

 

sort

: 배열의 요소를 정렬함. 문자열로 변환된 요소를 유니코드 코드 포인트의 순서에 따라 정렬함

 

이 메서드 역시 원본 배열을 변경하며, 변경된 배열을 반환한다. 사용자가 정렬 순서를 정의하고 싶다면, 비교 함수를 매개변수로 제공할 수 있다. 예를 들어, 숫자 배열을 정렬할 때는 숫자의 크기를 비교하는 함수를 사용해야 올바르게 정렬된다.

sort()는 기본적으로 문자열 비교를 사용한다.

숫자 배열을 정렬할 때는 비교 함수 (a, b) => a - b를 제공해 숫자 크기에 따라 정렬한다.

 

예시

let numbers = [3, 1, 4, 1, 5, 9];
numbers.sort((a, b) => a - b);

console.log(numbers);  // 출력: [1, 1, 3, 4, 5, 9]

 

 

slice 와 splice 의 차이점

slice 와 splice 는 이름이 비슷하지만 매우 다르다.

  • slice : 배열 또는 배열의 일부를 복사 가능
  • splice : 배열을 변경 (항목을 삽입하거나 삭제하기 위해)
  • React에서는 state의 객체나 배열을 변경하고 싶지 않기 때문에 slice (없음 p!)를 훨씬 더 자주 사용하게 될 것이다.

 

 

배열 내부의 객체 업데이트하기

객체는 실제로 배열 '내부'에 위치하지 않는다!

코드에서는 내부에 있는 것처럼 보일 수 있지만, 배열의 각 객체는 배열이 "가리키는" 별도의 값이다.

 

 

배열 내의 객체를 업데이트할 때, 배열은 객체에 대한 '참조를 저장'한다.


실제 객체는 배열 외부에 존재하고, 배열의 각 요소는 이러한 객체를 "가리키는" 참조로 구성된다. 따라서, 배열의 특정 요소(예: list[0])를 통해 객체의 속성을 변경할 때, 원본 객체가 직접 변경된다. 이는 React에서 상태 불변성을 유지하는 것이 중요한 이유 중 하나다.

 

객체를 수정할 때는 객체를 복사하고 수정한 후, 이를 새로운 상태로 설정해야 한다. 이렇게 하면 React에서 상태 변화를 감지하고 컴포넌트를 효과적으로 리렌더링할 수 있다.

 

 

 

[Reference]

 

 

4. 금일 소감

중간중간 드립 넣어가며 정리하면 더 행복하게 공부할 수 있다는 걸 깨달았다.

 

Immer라는 라이브러리를 몰랐는데 불변성을 위한 라이브러리고, useState 대신 사용하면 더욱 코드를 간결하고 깔끔하게 사용할 수 있다는 것을 새롭게 알게 되어 너무 유익하고 재밌었다.

 

기존에 알던 내용 계속 읽고 있으면 표정이 이렇게 된다

 

 

새로운 내용을 아는 건 늘 새롭고 짜릿하다..

아 그리고 복습 좀 열심히 해야겠다. 새로운 내용을 좋아하다 보니, 봤던 내용을 다시 안 보게 되는 불상사가,, 복습 파이팅...

 

728x90