1. Flux 패턴의 등장
양방향 데이터 바인딩으로 인한 상태 변경 코드 추적이 어려움을 문제의 원인으로 판단, 단방향 데이터 바인딩 방식 도입
action
: 어떠한 작업을 처리할 액션과 그 액션 발생 시에 함께 포함시킬 데이터
dispatcher
: 액션을 스토어에 보내는 역할
store
: 액션의 타입에 따라 값을 어떻게 변경할지가 정의됨
view
: 스토어에서 만들어진 데이터를 가져와 화면을 렌더링
2. props-drilling 문제 해결의 필요성
Props Drilling
: 리액트 컴포넌트 트리에서 데이터를 하위 컴포넌트로 전달하기 위해 중간 컴포넌트를 통해 프로퍼티를 내려주는 것
이러한 중간 컴포넌트는 원하는 자식 컴포넌트에게 프로퍼티를 전달하기 위해 필요하지만 해당 값을 직접 사용하지 않는 경우에도 프로퍼티를 받고 전달해야한다.
즉, Props Drilling을 통해 내려주는 깊이가 깊어질수록, 전달 과정을 매번 작성해야하는 비효율적인 상황이 발생한다.
3. 상태 변화 추적의 어려움
프로젝트가 커져서 컴포넌트의 개수가 많아지고, 컴포넌트 간 서로 공유하는 state 값들이 많아진다면 이들의의 변화를 추적하기 어렵다.
state가 어디서 어떻게 변하는지, 그리고 이 업데이트가 어떤 컴포넌트의 어떤 작업으로 인해 발생했는지를 손쉽게 파악하기 힘들어진다.
이에 여러 가지 상태들을 체계적으로 관리하기 위한 상태관리 라이브러리들이 등장하였다.
Redux
Flux 구조를 구현한 라이브러리로, 데이터의 흐름을 단방향으로 강제함
ELM 아키텍처 도입 : model
, view
, update
하나의 상태 객체를 스토어에 저장해두고, 이 객체를 업데이트하는 작업을 디스패치해 업데이트를 수행함
props-drilling 문제 해결
하고자 하는 일에 비해 보일러플레이트가 너무 많다는 단점이 존재
Context API
props-drilling 문제를 해결하고 싶지만, Redux의 보일러플레이트가 부담스러워 등장하게 된 기능
상태 주입을 도와주는 기능(상태관리X)으로, 렌더링을 막아주는 기능이 존재하지 않음
React Query, SWR
Recoil, Zustand, Jotai, Vatio
useState와 useReducer : 지역 상태
로, 해당 컴포넌트 내에서만 유효하다는 한계 존재
Recoil
atom(최소한의 상태 단위)은 key 값을 필수로 가짐
selector 함수를 사용해, 한 개 이상의 atom 값을 바탕으로 새로운 값을 조립할 수 있음
Jotai
작은 단위의 상태를 위로 전파하는 구조
Recoil의 한계를 보완한 라이브러리
Recoil의 atom 개념을 도입하면서도 API가 간결
Recoil과 달리 selector 함수 없이도 atom만으로 또 다른 파생된 atom 생성 가능
타입이 잘 지원되며, 리액트 18의 변경된 API를 원활하게 지원
atom 생성 시, 별도의 key를 넘겨주지 않음 (객체를 키로 활용하는 WeakMap 방식 활용)
Justand
하나의 스토어를 중앙 집중형으로 활용해 스토어 내부에서 상태를 관리 (리덕스와 비슷)
partial : state의 일부분만 변경하고 싶을 때 사용
replace : state를 완전히 새로운 값으로 변경하고 싶을 때 사용
API가 복잡하지 않고 사용이 간단헤 쉽게 접근할 수 있음