Part10_StateManagement
이효경
책 읽기

10장 상태 관리

10.1 상태 관리

10.1.1 상태

  • 상태 : 렌더링에 영향을 줄 수 있는 동적인 데이터 값
  • 지역상태 : 컴포넌트 내부에서 사용되는 상태 (보통 useState, useReducer와 같은 훅 사용)
  • 전역상태 : 앱 전체에서 공유하는 상태
  • 서버상태 : 사용자 정보, 글 목록 등 외부 서버에 저장해야 하는 상태

10.1.2 상태를 잘 관리하기 위한 가이드

  • 상태가 업데이트될 때마다 리렌더링이 발생하기 때문에 상태의 개수를 최소화는 것이 바람직

  • 어떤 값을 상태로 정의할 때는 다음 2가지 사항을 고려해야 한다.

    1. 시간이 지나도 변하지 않으면 상태가 아니다
    2. 파생된 값은 상태가 아니다
  • 시간이 지나도 변하지 않으면 상태가 아니다.

    • 시간이 지나도 변하지 않는 값이라면 객체 참조 동일성을 유지하는 방법을 고려해볼 수 있다.
    • 상수 변수를 저장하여 사용할수도 있지만 그러면 렌더링될 때마다 세로운 객체 인스턴스가 생성되기 때문에 컨텍스트나 props 등으로 전달했을 시 매번 다른 객체로 인식되어 불필요한 렌더링이 자주 발생할 수 있다.
    • 리액트 공식 문서에 따르면 useRef가 동일한 객체 참조를 유지하려는 목적으로 사용하기에 가장 적합한 훅이다
  • 파생된 값은 상태가 아니다

    • 부모에게서 전달받을 수 있는 props이거나 기존 상태에서 계산될 수 있는 값은 상태가 아니다
    • 파생된 값을 상태로 관리하게 되면 기존 출처와는 다른 새로운 출처에서 관리하게 되므로 정확성과 일관성을 보장하기 어렵다
    • 두 컴포넌트에서 동일한 데이터를 상태로 갖고 있을 때는 두 컴포넌트 간의 상태를 동기화하는 방법을 사용하지 않고 가까운 공통 부모 컴포넌트로 상태를 끌어올려서 SSOT를 지킬 수 있어야 한다.
  • useState vs useReducer, 어떤 것을 사용해야 할까

    • useState 대신 useReducer 사용을 권장하는 경우는 2가지가 있다
    1. 다수의 하위 필드를 포함하고 있는 복잡한 상태 로직을 다룰 때
    2. 다음 상태가 이전 상태에 의존적일 때
    • useReducer는 '무엇을 변경할지'와 '어떻게 변경할지'를 분리하여 dispatch를 통해 어떤 작업을 할지를 액션으로 넘기고 reducer 함수 내에서 상태를 업데이트하는 방식을 정의한다

10.1.3 전역 상태 관리와 상태 관리 라이브러리

  • 상태는 사용하는 곳과 최대한 가까워야 하며 사용 범위를 제한해야 한다
  • 어떠한 상태를 전역으로 사용하는 방법은 크기 2가지이다
  1. 컨텍스트 API + useState 또는 useReducer
  2. 외부 상태 관리 라이브러리(Redux, MobX, Recoil 등)
  • 컨텍스트 API
    • 다른 컴포넌트들과 데이터를 쉽게 공유하기 위한 목적으로 제공되는 API
    • 전역적으로 공유해야 하는 데이터를 컨텍스트로 제공하고 해당 컨텍스트를 구독한 컴포넌트에서만 데이터를 읽을 수 있게 된다
    • 컨텍스트 API 관련한 또 하나의 팁은 유틸리티 함수를 정의하여 더 간단한 코드로 컨텍스트와 훅을 생성하는 것이다
    • 컨텍스트 API는 대규모 어플리케이션이나 성능이 중요한 애플리케이션에서 권장되지 않는다
    • 그 이유는 컨텍스트 프로바이더의 props로 주입된 값이나 참조가 변경될 때마다 해당 컨텍스트를 구독하고 있는 모든 컴포넌트가 리렌더링되기 때문이다

10.2 상태 관리 라이브러리

  • MobX 특징
  1. 객체 지향 프로그래밍과 반응형 프로그래밍 패러다임의 영향을 받은 라이브러리
  2. MobX를 활용하면 상태 변경 로직을 단순하게 작성할 수 있고 복잡한 업데이트 로직을 라이브러리에 위임할수있다
  3. 객체 지향 스타일 코드가 편할 경우 추천
  • Redux 특징
  1. 특정 UI 프레임워크에 종속되지 않아 독립적으로 상태 라이브러리를 사용할 수 있다
  2. 오랜시간 사용되어 다양한 요구사항에 대해 충분히 검증되어 있음
  3. 상태 변경 추적에 최적화되어 있어 특정 상황에서 발생한 애플리케이션 문제의 원인파악하는데 용이하다
  4. 보일러플레이트 코드가 생기고 사용 난도가 높음
  • Recoil
  1. 상태를 저장할 수 있는 Atom과 해당 상태를 변형할 수 있는 순수함수 selector를 통해 상태를 관리하는 라이브러리다
  2. 보일러플레이트가 적고 난이도가 쉬워 배우기 쉽다
  3. 아직 실험적인 상태라서 다양한 요구사항에 대하 검증이 이뤄지지 않았다
  • Zustand
  1. Flux 패턴을 사용하며 많은 보일러플레이트를 가지지 않는 훅 기반의 편리한 API 모듈을 제공하다
  2. 클로저를 활용하여 스토어 내부 상태를 관리함으로써 특정 라이브러리에 종속되지 않는 특징이 있다
  3. 상태과 상태를 변경하는 액션을 정의하고 반환된 훅을 어느 컴포넌트에서나 임포트하여 원하는대로 사용할 수 있다