3 분 소요

React에서 프롭스를 통해 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달한다. 이 과정에서 ‘프롭스 드릴링’이라는 현상이 발생할 수 있는데, 여러 계층의 컴포넌트를 거치며 상태를 전달하다 보면 관리가 복잡해진다. 특히, 상위 컴포넌트에서 필요한 데이터를 하위에서 처리하는 경우, 코드가 비효율적으로 작성될 수 있다. 이런 문제를 해결하기 위해 전역 상태 관리 라이브러리를 사용하게 된다.

전역 상태란 여러 컴포넌트에서 공유해야 하는 상태를 의미하며, 이를 중앙에서 통합 관리하는 것을 전역 상태 관리라고 한다. 예를 들어, 로그인한 사용자 정보와 같은 데이터는 애플리케이션 전반에서 필요한 정보이기 때문에 전역 상태로 관리하는 것이 편리하다.

이제 그 중 하나인 Redux에 대해 알아보자.

redux란

Redux는 액션이라는 이벤트를 사용하여 애플리케이션 상태를 관리하고 업데이트 하기 위한 패턴과 라이브러리이다. 이는 전체 애플리케이션에서 사용해야 하는 상태에 대한 중앙 저장소 역할을 하며, 규칙은 상태가 예측 가능한 방식으로만 업데이트될 수 있도록 보장한다.

또한 Redux가 제공하는 패턴과 도구를 사용하면 앱의 상태가 ‘언제, 어디서, 왜, 어떻게’ 업데이트 되는지, 그리고 상태 변경이 발생할 때 앱 로직이 어떻게 동작하는지 더 쉽게 이해할 수 있다.

Redux는 다음과 같은 경우 더욱 유용하다.

  • 앱의 여러 곳에 필요한 대량의 애플리케이션 상태가 있을 때.
  • 앱 상태가 시간이 지남에 따라 자주 업데이트 되는 경우.
  • 해당 상태를 업데이트하는 논리가 복잡할 경우.
  • 앱이 중간 또는 대규모 코드베이스를 가지고 있으며 많은 사람들이 작업할 경우.
페이지네이션에 유용하다.

Redux는 3가지 원칙이 있다.

  • 데이터는 항상 같은 공간 (하나 뿐인 store)에서 관리한다
  • 액션 객체를 통해서만 상태를 변경할 수 있다
  • 상태 변경은 reducer라는 순수함수를 통해서만 변경할 수 있다

redux 특징

Redux는 Flux 패턴, 즉 단방향 데이터 흐름을 따른다. 자세한 내용은 아래와 같다.

  • dispatch
    • store에 액션 전달
  • store
    • 이전 상태로부터 업데이트 할 수 있도록 reducer 실행
    • 새로운 state 저장
    • 현재 변경된 state를 구독하는 모든 UI에게 업데이트 알림
  • 각 UI는 새로운 데이터로 렌더링

→ 스토어의 상태를 변경시키려면 액션을 디스패치 해야함

디스패치란

  • 액션을 발생시키는 것을 의미
  • 액션 객체를 전달하여 스토어에 상태 변화를 요청하는 역할 액션이란
  • 일종의 이벤트 객체로, 상태를 어떻게 변화시킬 지에 대한 정보를 포함 리듀서란
  • 이전 상태와 액션을 받아서 새로운 상태를 반환하는 순수 함수
  • 상태의 변화는 모두 리듀서를 통해 이루어짐
  • 리듀서는 이전 상태를 변경하지 않고, 새로운 상태 객체를 생성하여 반환

redux로 API 호출할 경우, reducer가 순수함수이기에 비동기 호출을 할 수 없다. 그렇기에 redux 미들웨어인 redux-thunk를 통해, 앱 로직과 비동기 데이터 호출 로직을 구분한다. 또한 비동기 데이터를 전역으로 관리할 필요가 생길 경우가 있을 수 있으므로 redux로 호출하는 경우가 많다.

순수함수란? 사이드 이펙트가 없는 함수, 즉 함수의 실행이 외부에 영향을 끼치지 않는 함수를 뜻하고, 입력으로 전달된 값을 수정하지 않는 불변성을 가지고 있다

중앙 집중식 상태 관리

  • Redux는 애플리케이션의 상태를 중앙에서 관리
  • API 호출을 통해 얻은 데이터도 이 중앙 상태에 저장하면, 애플리케이션의 여러 컴포넌트에서 이 데이터를 쉽게 접근하고 사용 가능.
  • 더불어 redux-thunk를 사용하면
    • API 호출이 완료된 후, 응답 데이터를 기반으로 다양한 액션을 디스패치 할 수 있다.
    • 예를 들어, API 호출 성공 시 성공 액션을, 실패 시 실패 액션을 디스패치 할 수 있다.

redux-toolkit

Redux Toolkit은 효율적이고 표준화된 Redux 로직을 작성하기 위해 만들어진 도구이다.

이 도구는 저장소 설정, 리듀서 정의, 불변성 유지, 그리고 액션 생성자나 액션 타입을 직접 작성할 필요 없이 전체 상태 “조각”을 생성하는 등 대부분의 Redux 작업을 간소화하는 유틸리티 함수들을 포함하고 있다. 또한 비동기 로직을 관리하기 위한 Redux Thunk와 셀렉터 작성을 위한 Reselect 같은 널리 사용되는 애드온도 내장되어 있어, 복잡한 로직도 쉽게 처리할 수 있다.

앞서 언급한 대로, Redux에서는 비동기 작업과 관련된 대표적인 미들웨어 라이브러리로 Redux Thunk와 Redux Saga가 있다. 이 중 Redux Thunk는 Redux Toolkit에 기본으로 내장되어 있어, 별도의 설정 없이 바로 사용할 수 있다. 이를 통해 비동기 작업을 보다 간편하게 처리할 수 있으며, 복잡한 상태 관리를 더 쉽게 구현할 수 있다.

아래는 redux 공식 홈페이지 설명이다.

Redux Toolkit은 모든 Redux 앱에서 가장 일반적으로 하는 작업을 간소화하는 두 가지 주요 API로 시작한다:

  • configureStore는 한 번의 호출로 Redux 스토어를 설정하며, 리듀서를 결합하고 thunk 미들웨어를 추가하고, Redux DevTools 통합을 하는 등의 작업을 수행한다. 또한, 이름이 있는 옵션 매개변수를 사용하기 때문에 createStore보다 구성이 쉽다.
  • createSlice는 Immer 라이브러리를 사용하는 리듀서를 작성할 수 있게 해준다. 이를 통해 state.value = 123과 같은 “변형 (mutating)” JS 문법을 spreads 없이도 불변성을 유지하며 업데이트할 수 있다. 또한, 각 리듀서에 대한 액션 생성자 함수를 자동으로 생성하고, 리듀서 이름에 기반하여 내부적으로 액션 타입 문자열을 생성한다. 마지막으로, TypeScript와 잘 호환된다.

그 외 라이브러리

  • mobx
    • Redux와 다르게 간결하고 깔끔한 구조를 가졌으며, 함수형 프로그래밍을 투명하게 적용함으로 상태 관리를 쉽고 확장성 있게 만들어주는 검증된 라이브러리이다.
  • jotai
    • Jotai는 recoil에서 영감을 받아 Atomic 모델과 함께 bottom-up 방식으로 접근한다. Atom과 함께 상태를 생성하고 아톰 의존성에 따라 렌더링 최적화를 하는데, 이 방식을 통해 리액트 컨텍스트의 리렌더링 이슈를 해결하고, 메모이제이션의 의존도를 줄일 수 있다.
  • recoil
    • Recoil은 2020년에 Facebook에서 발표하였으며, React의 Concurrent Renderer (동시성 렌더링) 를 공식 지원하는 유일한 상태 관리 라이브러리다.
  • zustand
    • Zustand란 상태라는 뜻을 가진 독일어이다. 단순화된 Flux 원리를 사용하는 작고 빠르며 확장 가능한 상태 관리 솔루션이다. Hooks에 기반해 편리한 API를 제공한다.

업데이트: