치춘짱베리굿나이스

redux + toolkit 본문

ClientSide/라이브러리

redux + toolkit

치춘 2022. 5. 21. 22:12

Redux toolkit

설치

$> npm i @reduxjs/toolkit 
$> yarn add @reduxjs/toolkit

npm 링크

@reduxjs/toolkit

 

@reduxjs/toolkit

The official, opinionated, batteries-included toolset for efficient Redux development. Latest version: 1.8.1, last published: 2 months ago. Start using @reduxjs/toolkit in your project by running `npm i @reduxjs/toolkit`. There are 1388 other projects in t

www.npmjs.com

yarn 링크

Contributors

 

https://yarnpkg.com/package/@reduxjs/toolkit

Fast, reliable, and secure dependency management.

yarnpkg.com

설명

상태관리 라이브러리 중에서도 가장 많이 쓰이는 Redux의 편의성 개선 버전

리액트에 기본으로 탑재된 상태관리 훅으로 Context API가 있긴 하지만, 많은 개선을 거치기 전까진 사용 방법이 좀 까다로워서 (지금도 속도나 코드 길이면에서 사용하기엔 조금 별로이다) 대체재로 많이 사용되었던 라이브러리이다

지금은 Recoil이 리액트와 찰떡궁합인 전역 상태관리 계의 신흥 강자로 떠오르고 있긴 하지만, 알파 버전이라는 점과 등장한지 얼마 안 돼 자료가 별로 없다는 것이 흠이다

이러나저러나 Redux는 Recoil이나 Mobx 등보다 훨씬 빨리 나와서 꾸준한 업데이트 및 개선 버전으로 압도적인 사용량을 자랑하는 라이브러리이기에, 짚고 가는 것이 프로젝트 진행에 도움이 된다

또한 툴킷의 존재로 과거의 복잡함을 탈피하고 간단한 사전 설정과 훅의 사용으로 손쉽게 상태값을 다룰 수 있게 되어 난이도가 많이 내려갔으므로, 리덕스를 처음 시작하는 사람들에겐 툴킷 사용이 적극 권장된다 (툴킷을 쓰지 않는 경우는 클래스형 컴포넌트밖에 없다고 한다)

특징

  • 단 하나의 Store에서 모든 상태값을 관리한다 (중앙 집중식)
  • 상태값이 읽기전용으로 관리된다 (dispatch를 통해서만 상태값 변경이 가능하며, 상태값을 받아올 때도 get이 필요하다)
  • Reducer는 순수 함수로만 구성되며, 오직 인자값에만 영향을 받고, 외부 요인에 내부 값이 영향을 받지 않는다

장점

  • 데이터의 흐름이 한 방향으로만 흐른다
    1. 컴포넌트 등에서 이벤트 발생 (Action Creator 호출)
    2. Action Creator에 의해 생성된 Action 호출
    3. dispatch 호출
    4. Store에서 reducer 호출
    5. Action과 Dispatch, reducer에 의해 Store 내의 상태값 변화
    6. 컴포넌트에서 새 상태값 받아와서 렌더링
  • Store에서 모든 데이터를 한번에 전달해주므로 복잡한 계층 구조를 생각할 필요 없이 각 컴포넌트가 스토어를 구독하기만 하면 된다
  • Redux의 복잡한 함수 사용 구조, 대량의 라이브러리를 설치해야 보완가능하던 동작들이 toolkit에 의해 한번에 처리되어 쉽게 사용할 수 있으며, 보일러플레이트의 작성도 쉬워졌다
  • 상태 업데이트 함수의 덩치가 크지 않아 (전부 Store에 저장되어 있고, 컴포넌트에서는 그걸 가져다 쓰기만 하면 되기 때문에) 컴포넌트의 코드가 기하급수적으로 커지지 않는다
  • 미들웨어의 존재로 액션을 다루거나 액션에 대한 후속동작을 제어함에 따라 비동기 작업을 처리할 수 있다

데이터의 흐름

Action

객체이며, 상태값을 바꾸는 이벤트에 대한 정보가 담겨있다

Reducer

상태값을 바꿔주는 주체이며, Action과 기존 상태값 (State) 을 인자로 받아 새로운 상태값을 반환한다

내부에서는 Action을 이용하여 State를 어떻게 바꾸어 줄 지 정의하며, 다른 어떠한 값에도 의존하지 않고 인자로 들어온 두 값만 이용하여 새로운 상태 객체를 반환한다

Store

프로젝트에서 리덕스 상태를 저장하는 중앙 저장소

상태값과 리듀서를 포함하고 있으며, 사용자는 Store에 저장된 상태를 읽어오기 위해 getState, 상태를 바꿔주기 위해 dispatch를 사용한다

용례

1. 사전 설정하기

import { Provider } from 'react-redux';
import { store } from './states'; // 전역 상태값 저장하는 store 위치
...
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
    <React.StrictMode>
        <Provider store={store}>
            <BrowserRouter>
                <Routes />
            </BrowserRouter>
        </Provider>
    </React.StrictMode>
);

리코일, 리액트 쿼리와 같이 리덕스도 최상위에 Provider 컴포넌트로 앱을 감싸줘야 한다

아래에서 정의할 Store를 불러오면, 앱 내의 모든 컴포넌트가 해당 스토어를 구독하게 되며, 스토어 내의 리듀서와 상태값을 다룰 수 있게 된다

대개 라우터가 앱 컴포넌트의 최상단에 있으므로, 라우터를 감싸 주면 모든 컴포넌트를 감싸는 형태로 구성이 가능하다

2. Store 정의하기

import { configureStore } from '@reduxjs/toolkit'

import dropdown from './dropdown'
import search from './search'
import modal from './modal'

export const store = configureStore({
  reducer: {
    dropdown,
    search,
    modal,
  },
  devTools: process.env.NODE_ENV !== 'production',
  middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false }),
})

export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch

상태값과 리듀서를 가지고 있는 스토어를 정의한다

이 스토어가 위의 Provider의 인자로 들어가는 스토어이다

컴포넌트들은 스토어를 구독함으로써 여기에 정의되는 상태값과 리듀서에 접근할 수 있게 된다

스토어의 reducer에는 사용할 상태값 슬라이스의 이름을 넣자

미들웨어 (middleware) 는 기본값으로 설정하고, 데브툴 (devTools) 은 배포 단계가 아닐 때에만 사용할 수 있도록 선언한다

3. 상태값 정의하기

import { createSlice, PayloadAction } from '@reduxjs/toolkit';

import type { RootState } from '.';

export interface SystemState {
    theme: string;
}; // 테마 타입 지정

const INITIAL_STATE: SystemState = {
    theme: store.get('testApp.theme') || 'light',
}; // 로컬 스토리지에서 값 가져오기 시도하고 없으면 light로 지정

const systemSlice = createSlice({
    name: 'system',
    initialState: INITIAL_STATE,
    reducers: {
        setTheme: (state: SystemState, action: PayloadAction<string>) => {
            state.theme = action.payload
        }, // 테마를 지정할 수 있는 setTheme 함수
                // 리듀서 함수 추가하고 싶다면 아래에 key-value로 추가
    },
});

export const { setTheme } = systemSlice.actions;

export default systemSlice.reducer;

export const getTheme = (state: RootState): string => state.system.theme;
// 테마를 가져올 수 있는 getTheme

상태값, 초기값, 이 상태값을 다루는 리듀서를 선언하자

initialState로 초기값을 정의할 수 있고, reducers 내의 함수들은 store 내의 상태값을 변화시킨다

setThemecreateSlice로 생성한 슬라이스의 actions를 가져오고, getThemestate.[Store에서 불러오는 이름].[사용하고자 하는 상태값 이름] 형식으로 불러와서 export한다

슬라이스의 액션을 setTheme과 같은 이름으로 export함으로써, 컴포넌트들은 액션과 리듀서를 이용하여 상태값을 조작할 수 있다

툴킷이 없었을 땐 액션과 리듀서 등을 다 별개로 작성했어야 하는데, 툴킷 덕에 슬라이스 생성 한 번으로 간단하게 액션과 리듀서, 상태값을 선언할 수 있게 되었다

여기서 선언된 모든 값들은 중앙의 Store에서 관리된다

4. useDispatch, useSelector

// dispatch
import { useDispatch } from 'react-redux';
import type { AppDispatch } from 'states/index';

export const useAppDispatch = (): AppDispatch => useDispatch<AppDispatch>()

// selector
import { TypedUseSelectorHook, useSelector } from 'react-redux'
import type { RootState } from 'states/index'

export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

위의 방식은 타입스크립트 타입 때문에 함수 형태로 한번 감싸 반환하는 것이고, 원래는 useDispatch, useSelector만 사용해도 무방하다

useDispatch는 액션을 사용하여 상태값을 수정할 때 사용하고, useSelector은 스토어에서 상태값을 가져올 때 사용한다

import { useAppSelector } from 'hooks'; // get함수 가져올 때 필요
import { getTodoList } from 'states/todo';

const TodoList = () => {
    const todoList = useAppSelector(getTodoList);

스토어상의 상태값을 사용하고 싶으면 아까 export했던 get 함수와 useSelector를 사용한다

import { useAppDispatch } from 'hooks'; // set함수 가져올 때 필요
import { setTodoList } from 'states/todo';

const TodoItem = ({ todo }: Props) => {
    const dispatch = useAppDispatch(setTodoList);
    ...
    dispatch(setTodoList({ /* 상태값 */}));

상태값을 바꾸고 싶다면 useDispatch와 set 리듀서를 이용하여 dispatch를 가져오고, dispatch에 set 함수를 인자와 함께 넣어주자

리듀서 함수의 내용에 따라 상태값을 어떻게 바꾸어줄지, 인자로는 무엇을 사용할 지 결정해줄 수 있다

결론

전체적인 흐름은 위와 같이 설정한 스토어와 리듀서, 액션, 디스패치, 상태값을 이용하여 진행된다

툴킷을 통해 나름 간결하게 작성할 수 있고 모든 컴포넌트와 상태값에 대하여 정형화된 코드 패턴을 사용할 수 있다

다양한 작업에 사용해 보자

참고자료

Redux는 무엇이고, 어떤 장점이 있는가?

 

Redux는 무엇이고, 어떤 장점이 있는가?

 첫 프로젝트 때는 클라이언트 사이드 구성에서 데이터 흐름에 대해 하위 컴포넌트들이 깊게 들어가지 않으니 상태 끌어올리기로도 충분히 작성이 가능할 것이라 생각하고 진행했었다. 하지만

jjy0821.tistory.com

6장. 리덕스

 

6장. 리덕스 · GitBook

이번 챕터에서 알아볼 주제는 리덕스(Redux) 입니다. 리덕스는 리액트 생태계에서 가장 사용률이 높은 상태관리 라이브러리입니다. 리덕스를 사용하면 여러분이 만들게 될 컴포넌트들의 상태 관

react.vlpt.us

Redux Toolkit으로 리덕스 쉽게 사용하기

 

Redux Toolkit으로 리덕스 쉽게 사용하기

지적되어온 Redux의 문제점들 리덕스(Redux)는 리액트(React)의 상태 관리 라이브러리 중 대표로서 굳게 자리매김하고 있었지만, 그동안 리덕스가 사용하기 너무 복잡하고 배우기 어렵다는 의견이

cocoder16.tistory.com

 

'ClientSide > 라이브러리' 카테고리의 다른 글

Victory  (0) 2022.05.30
구글 애널리틱스  (0) 2022.05.29
react-query 1. useQuery  (0) 2022.05.20
gh-pages로 리액트 프로젝트 배포 + 404 에러처리  (1) 2022.05.15
React-Beautiful-Dnd  (0) 2022.05.15
Comments