리덕스 #5. 리덕스 툴킷

김동욱·2021년 11월 5일
0

리덕스

목록 보기
5/5
post-thumbnail

리덕스를 사용하면서 불편한 점은 한두가지가 아니다

  • "Redux 저장소 구성이 너무 복잡합니다"
  • "Redux가 유용한 기능을 수행 할 수 있도록 많은 패키지를 추가해야 합니다."
  • "Redux에는 boilerplate 코드가 너무 많이 필요합니다"

리덕스 툴킷에는 리덕스에서 자주사용되는 코드와 로직들을 훨씬~ 편하게 만들어주는 리덕스 라이브러리이다. 물론 리덕스의 기본원리는 변하지않으며 반복적인 작업들을 훨씬 줄여준다.

미리 배웠다면 좋겠지만 리덕스의 원리를 알기위해선 오리지널 리덕스를 알아야하기때문에 오리지날 리덕스를 배우고오자.

전에 사용하던 코드에서 리덕스 툴킷을 적용해보았다. 결과는 똑같고 방법도 똑같다.

import axios from 'axios'
import pkg from '@reduxjs/toolkit';
const { configureStore, createSlice, createAsyncThunk } = pkg;

const printAsync = createAsyncThunk('toolkitReucer/printAsync', async (post, thunkAPI) => {
    const response = await axios.get('https://jsonplaceholder.typicode.com/todos/1')
    return response.data
})
  
const initalState = {
  nowState: "inital",
  payload: 0
}

const Reducer = createSlice({
    name: 'toolkitReucer',
    initialState: initalState,
    reducers: {
        increase(state, action){
            state.payload += 10,
            state.nowState = "Increse!"
        },
        decrease(state, action){
            state.payload -= 5,
            state.nowState = "Decrese!"
        }
    },
    extraReducers: {
        [printAsync.pending](state, action) {
            state.payload = "wait...",
            state.nowState = "Pending!"
        },
        [printAsync.fulfilled](state, action) {
            state.payload = action.payload.title,
            state.nowState = "Async!"
        },
        [printAsync.rejected](state, action) {
            state.payload = "error",
            state.nowState = "Error!"
        }
    },
})

const store = configureStore({
    reducer: Reducer.reducer
})

store.subscribe(() => {
  const state = store.getState();
  const nowState = state.nowState;
  const payload = state.payload;
  console.log(`now state is '${nowState}' and payload title is '${payload}'`)
})

store.dispatch(Reducer.actions.increase());
store.dispatch(printAsync());
store.dispatch(Reducer.actions.decrease());


코드의 양이 반으로 줄었다! 퇴사한 만큼 기분이 좋다. 하나씩 알아보자


createAction과 creatReducer는 리뷰를 안하겠습니다. 왜냐하면 createSlice에서 전부 만들수 있습니다!

1. configureStore

이 함수는 기본적으로 createStore와 동일한 기능을 제공합니다. configureStore함수는 여러 개의 인자 대신 이름이 지정된 하나의 object를 인자로 받으므로, reducer함수를 reducer라는 이름으로 전달해야 합니다.
아마 크게 다른것 처럼 보이지는 않을 것입니다. 그러나 configureStore를 통해 생성 된 store는 Redux DevTools Extension을 사용하여 dispatch된 action과 history 그리고 state변경사항들을 쉽게 볼 수 있습니다.
그리고 Redux middleware가 기본적으로 포함되어 있습니다.

2. createSlice

객체에 reducer함수들을 제공할 수 있고 이를 기반으로 액션 타입문자열과 액션 생성자 함수를 자동으로 생성합니다.
createSlice는 생성된 reducer함수를 reducer라는 필드를 포함하는 "slice"객체와 actions라는 객체 내부에서 생서된 액션 생성함수를 반환합니다.

  • name : 리듀서의 이름을 정합니다.

  • initialState : 말그대로 초기 상태값을 넣어줍니다.

  • reducers: 우리가 잘아는 그 리듀서를 넣어줍니다. 리듀서를 만들면 이름이 곧 액션명이 되고 반환되는 객체가 액션값이 됩니다. 첫번째 파라미터는 상태값이고, 두번째는 액션값입니다.

    특이한 점은 액션값의 type이름은 그대로인데 이제 상태값이 들어가는 키명이 payload로 고정이 되었습니다.
    그리고 이제 객체를 복사할 필요도 없습니다.

  • extraReducers : 툴킷에는 기본으로 thunk가 내장되어있어 비동기 작업이 가능합니다. 비동기 작업을 할 액션들을 여기에 넣어줍니다. 대신 reducers처럼 slice에서 액션을 만드는 것이 아닌 createAsyncThunk로 만든 비동기 함수를 넣어주어야한다.

3. createAsyncThunk

말그대로 thunk함수를 만들어주는 객체이다. 첫번째 파라미터엔 함수의 이름, 두번째 콜백에는 비동기 처리할 함수를 넣는다. 그리고 비동기 처리값을 리턴한 객체를 extraReducers에 넣고 상태별로 함수를 하나씩 만든다. 상태는 promise처럼, pending, fulfilled, rejected 상태를 가진다. 각각 상황에 맞는 액션을 넣어주자


여기까지 알아몬 툴킷의 장점은

  • action type이나 action creator를 따로 생성해주지 않아도 된다.
  • 미들웨어 추가가 편리하다.
  • immer가 내장되어 있어 mutable 객체를 사용해도 된다.
  • redux thunk가 내장되어 있어 비동기를 지원한다.
  • 타입스크립트 지원이 잘된다.

오리지널 리덕스를 경험해본 입장에선 인생의 절반을 손해본 느낌이다. 앞으로 리덕스 툴킷을 매우 애용할거같다.

profile
안녕하세요. 부산에서 근무하고 있는 프론트엔드 개발자 김동욱입니다. 영어 공부 겸 개발 공부를 위해서 글을 작성하고있습니다.

0개의 댓글