Final Project에서 상태관리 Tool로 Context API, Recoil, Redux중에서 선택해야 했다.
Context API와 Recoil은 수업 도중 멘토님들이 추천해주셨으나 이름만 들어본 상태였고,
Redux는 강의 중에 잠시 언급되어 코드도 본적은 있고 관련 유튜브 강좌도 한두번은 찾아본
적이 있어 간편화된 Toolkit으로 적용하기로 했다.
당시 멘토분들은 Redux를 적용하겠다는 초보들에 대해 " 그렇게까지?" 혹은 "해보고 싶으면
경험삼하 해 봐라"는 입장을 보이셨는데, 하루만에 기술스택과 프로젝트 구성범위까지 정해야
하니 상태관리 도구에 스터디할 시간적 여유가 없었다. 우리가 구성했던 Redux구성을 파보기
전에 관련 툴들을 한번쯤은 정리하고 넘어가고자 한다.
Context API
ContextAPI는 리액트 자체에서 상태를 props-drilling없이 전달하기 위해 제공하는 API로,
리액트의 컴퍼넌트 구조를 이용하여 상태의 변경사항을 전역적으로 관리(??)할수 있다.
필요한 상태의 내용을 정의하여 Context객체를 생성하고 상태값을 설정하여, Provide라는
부수적인 객체의 형태로 리액트의 트리의 상위 구조로 배치하면 하위 컴퍼넌트에서
전달(구독)받는 형태로 공유된다.
1. 관리할 상태의 종류 및 값 설정
(1) state를 관리하는 주체 : Context객체
- state 성격에 따라 복수개의 context객체 생성 ( 하위 컴퍼넌트에서 필요한 context구독 )
- 상태의 기본값과 변경 옵션, 상태변경 함수정의
(2) state의 상태값 관리
- current value설정 : Context.Provider컴퍼넌트의 value로 설정
2. 컴퍼넌트 상태값 변경
상태값은 해당 상태가 저장된 Context.Provider의 하위 컴퍼넌트에 적용가능
(1) 외부에서의 상태변화를 하위 컴퍼넌트에 반영하는 두가지 방법
- 컴퍼넌트를 Context.Consumer로 감싼 노드로서 구성(구독과 유사)
- useContext훅으로 상태값 호출 ( 트리 구조상 가장 근접한 Provider의 상태값 전달)
- 여러 Context객체의 상태를 공유받을 수 있음
(2) 컴퍼넌트 내부의 상태변화를 외부로 (전역적) 공유
- 미리 정의된 메서드를 활용하여 context객체에 전달
Conext API는 상태를 관리하기보다는 공유하는 기능이지만, useReducer혹을 결합하여
상태저장소와 유사한 기능을 만들수 있다고 한다. 리액트 자체 API이므로 상태값에 일정한
규칙이나 옵션을 적용하고 싶은 경우 자체 기능인 useState나 action등으로 이용해 쉽고
자유롭게 구성할수 있는 장점이 있다.
다만 Provider의 상태값 변경 시 하위 컴퍼넌트가 모두 렌더링되므로 이를 방지하려면
memo함수를 사용해 컴퍼넌트를 감싸는 코드를 구성해야 한다. 또한 context적용에 의해
함수 기능이 제한된다거나 컴퍼넌트 재사용에도 영향이 있어, 상태값의 유형이 단순하고
상태 변화가 적은 소규모의 프로젝트에 적합하다.
Recoil
Recoil은 리액트의 State Management Library이다. 기본적으로 상태를 작은 단위로 관리하기
위한 atom과 관련 함수인 selector로 구성된다.구조분해할당을 활용하거나 상태값의 변경이
Hook으로 전달되는 등 리액트의 기본적인 문법과 사용방법이 녹아있다.
1. 관리할 상태의 종류 및 값 설정
(1) state를 관리하는 주체 : atom으로 생성된 객체
- 상태 key와 default value 선언
(2) state의 상태값 관리 : selector함수로 생성된 상태변경함수로 관리
get : 상태 key를 매개변수로 사용하여 atom과 연결
상태값을 가지며, 상태변경시 (useRecoilValue로) 관련 컴퍼넌트에 전파
set : 비동기 처리시에 사용
2. 컴퍼넌트에 상태값 변경
(1) 외부의 상태변화를 컴퍼넌트에 반영
- useRecoilValue훅으로 상태값 확인(Selector의 상태변경함수를 인자로 받음)
(2) 내부의 상태변화를 전역적으로 공유
- 컴퍼넌트 내부에 이벤트를 취급하는 함수 생성
- useRecoilState(atom의 상태 key를 인자로 받음)로 이벤트 함수와 atom연동
- atom의 key를 통해 상태변경함수에 전달되어 상태값 변동
통합관리 위해 Recoil Root를 생성하여 전체를 감싸주면 위의 내용과 같이 간단한
설정만으로 상태의 전역관리가 가능하다. 쉽고 간편하지만 메모리 누수나 내부적인 오류,
캐싱등의 문제가 지적되고 있다.
Redux
리덕스는 자바스크립트 앱을 위한 State Management Library로서 모든 상태 데이터를
스토어에서 전역으로 상태를 관리한다. 상태의 종류와 상태가 변경될수 있는 활동이나 변경에
대한 제반 규칙을 사전에 정의한 뒤 이벤트가 발생하면 이를 스토어에 전달하여 update한다.
상태값에 영향을 주는 활동의 종류와 범위는 action이라는 객체로서 미리 정의되어 있으며
action에 의해 현재 상태를 어떻게 혹은 얼마나 변경할 것이가의 규칙은 reducer에 정의된다.
action이 dispatch라는 이벤트 핸들러를 통해 reducer로 전달되며, 개별 컴퍼넌트는 스토어를
구독하여 상태값을 전달받는다.
Redux ( Original )
1) 상태정의 : 관리할 상태의 종류 구분하여 명명하고, 각 상태에 대한 세부값의 종류
혹은 수적인 범위, 상태변화를 발생시키는 활동에 대해 정의한다.
2) initial state 정의 : 상태의 초깃값을 정의하는 객체 생성
3) action함수정의 : 상태를 변경시키는 활동의 내용과 수준(값)에 따라 복수의 객체 생성
4) action생성함수정의 : action을 스토어에 dispatch하는 함수 생성
4) reducer생성 : action의 내용과 수준에 따라 상태값 변화를 결정하는 함수 생성
5) 스토어 생성 : 스토어에 다수의 리듀서를 연동
6) 컴퍼넌트에 구독생성 : 하위 컴퍼넌트에 스토어의 특성한 상태를 구독하도록 함수설정
7) 컴퍼넌트와 리덕스 연결 : connect함수로서 리덕스 스토어안에 넘겨주는 객체 생성
이러한 복잡한 흐름은 아래와 같으며 이를 단순히 하기 위해 Toolkit이 개발되었고 데이터의
간편한 전달을 위해 Hook이 사용되고 있다.
Redux Toolkit으로 인한 변경사항과 Hooks
1) Slice : action함수 정의 및 생성자 자동연동, 상태 초기값, 리듀서를 통합
Thunk를 이용해 비동기로 받아온 데이터로 상태값 update가능
2) configureStore: reducer의 내용을 모아서 store설정 간편화
useSelector: 리듀서에 접근하여 상태값을 가져오는 hook (connect 생략가능)
useDispatch : action의 내용을 리듀서로 보내는 hook
1. 관리할 상태의 종류 및 값 설정
(1) state를 관리하는 주체 : store (어플리케이션의 전체 상태를 통합관리)
관리하고자 하는 상태에 대한 적용 규칙을 설정한 reducer 연결
(2) state의 상태값 관리 : reducer(상태변경함수), dispatch, action
- current value관리 : 스토어에서 리듀서를 통해 관리
- reducer : 상태변경 규칙정의, 상태가 많은 경우 다수의 reducer필요
- action : 상태값을 변화시킬수 있는 동작을 객체 형태로 정의
- dispatch : action발생시 관련 값을 reducer로 전달하는 이벤트 핸들러
2. 컴퍼넌트에 상태값 변경
(1) 외부의 상태변화를 컴퍼넌트에 반영
- useSelect를 이용하여 slice내의 상태값을 확인
(2) 내부의 상태변화를 전역적으로 공유
- 컴퍼넌트 내부에 이벤트를 감지하는 함수 생성
- 이벤트에 함수를 연동하여 슬라이스의 action으로 전달 (useDispatch사용)
리덕스는 Toolkit과 Hook으로 편의성을 높였다고 해도 기본적으로 설정할 내용이 많았다.
우리는 상태 관리 자체에 대해 그다지 의논하지 않고 개별로 설정을 했는데, 만약에 세부
사항을 협의를 했다면 더(??!!) 복잡했을것 같다.
또한 Thunk를 이용한 비동기 설정은 Typescript를 적용할때 다양한 오류가 있었으나 표준
문서에 구체적인 설명이 없어서 어려웠다. 오류 발생시 원인을 찾으려고 redux devtool을
설치하였으나 큰 도움은 되지 않았다. 전반적인 설명으로 보면 완벽한 상태관리 Tool인데
권하시지 않는 이유를 한번 적용해보면서알게 되었다.
(국내 N포털에 근무하시는 멘토 분도 사내에서 Recoil을 활용한다고 하셨다 )
최근 리액트의 state management library사용비율을 보니 Zustand가 점차로 늘어나고
있는 추세이다. 항상 새로운 솔루션을 익혀가는 것이 프론트의 숙명이라고 하셨는데,
상태관리도구는 오늘도 진화중인가보다.