FE/Redux

[Redux Toolkit] 리덕스 툴킷에 대한 개념공부하기

mandelina 2022. 7. 12. 01:23
리덕스만으로도 정말 좋은 라이브러리지만 문제점이 있었다!



리덕스의 문제점은 ? 

 

1. 리덕스 스토어 환경 설정이 너무 복잡

2. 리덕스는 보일러플레이트 (어떤일을 하기전 반복하여 작성하는 코드들)이 너무 많다.

3. 리덕스를 유용하게 사용하려면 많은 패키지들을 추가해야한다.

4. 불변성유지의 어려움 

 


 

 

이런 이슈들을 해결하기 위해 Redux Toolkit이 등장한다.

리덕스툴킷을 이용하면 

리덕스 툴킷을 들어가기 앞서서 아래 3가지를 비교해보자

 

Redux React Redux Redux toolkit
createStore
subscribe
getState
dispatch
connecct
useDispatch
useSeletor
configuerStore
createSlice
createAsyncThunk

 

기존에 리덕스를 사용하셨던 분이라면 기존 함수들이 익숙할것이다 .

(저 또한 리덕스부터 배워가지고 사실 앞에께 더 익숙한 . .)

 

 

이 포스팅은 Redux를 안다는 전제하에 작성하겠다! 

 

 


1. 설치하기 

 

새롭게 프로젝트를 시작한다면

# Redux + Plain JS template
npx create-react-app my-app --template redux

# Redux + TypeScript template
npx create-react-app my-app --template redux-typescript

 

기존 프로젝트에 추가한다면

# NPM
npm install @reduxjs/toolkit

# Yarn
yarn add @reduxjs/toolkit

 

 

2. Redux toolkit에 있는 API들 

 

1) configureStore ()

 

- reducers에서 반환된 새로운 stateStore객체로 정리해 관리하는 곳이다.

 

- 리덕스 코어 라이브러리의 표준함수 createStore를 추상화 한 것이다.

 

- 자동으로 Slice reducer들을 combine한다.

 

- redux-thunk 를 기본적으로 포함하고 , Redux DevTools Extension을 사용할 수 있다.

 

2) createReducer ()

- 기존 swich 문과 보일러플레이트로 작성하는 방법에서 쉬운구조로 바뀌었다.

 

- RTK에서 case reducer가 액션을 처리하는 방법은 2가지이다. ( builder callback표기법 , map object표기법)

 

- TypeScript 호환을 위해선 builder callback표기법이 선호된다.

 

3) createAction ()

 

- 기존 리덕스에서 액션을 정의할때에는 액션타입상수와 액션 생성자 함수를 분리하였다.

 

- RTK에서는 이러한 두과정으 합쳐 createAction함수를 사용하여 하나로 결합하여 추상화

 

- 함수 자체가 toString()으로 정의되어 있기때문에 상수 대신 사용가능하다.

 

 

 4) createSlice ()

- 리듀서 함수의 객체, slice이름 , initialState 를 받아 해당 액션 생성자와 액션 유형으로 슬라이스 리듀서를 자동 생성한다.

 

- 한마디로 초기값 + 액션생성자 + 리듀서 기능을 가지고 있는 것

 

 

5) createAsyncThunk ()

 

- createAction의 비동기 버전을 위해 제안

 

- 액션 타입 문자열프로미스를 반환하는 콜백함수를 인자로 받는다.

 

- 주어진 액션 타입을 접두어로 사용하는 프로미스 생명 주기 기반의 액션 타입을 생성한다.

 

 


 

실습

 

1. Store.js

import { configureStore } from '@reduxjs/toolkit'

export const store = configureStore({
  reducer: {},
})

- configureStore를  RTK API에서 가져온다. 빈 Redux 저장소를 만들고 export한다.

- 이렇게 하면 Redux store이 생성되고, Redux DevTools 확장도 자동으로 구성된다.

 

 

 

 

 

2. index.js

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import { store } from './app/store'
import { Provider } from 'react-redux'

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

- store과 Provider을 가져온 후 import 해준다.

- 이때  <Provider>로 <App/>를 감싸준다.

 

 

 

 

3.  counterSlice.js

import { createSlice } from '@reduxjs/toolkit'  // createSlice가져오기 

const initialState = {   //초기값 설정
  value: 0,
}

export const counterSlice = createSlice({
  name: 'counter',    // 1️⃣ 
  initialState,       // 2️⃣
  reducers: {         // 3️⃣
    increment: (state) => {
      state.value += 1
    },
    decrement: (state) => {
      state.value -= 1
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload
    },
  },
})


export const { increment, decrement, incrementByAmount } = counterSlice.actions  //4️⃣

export default counterSlice.reducer  //5️⃣

- createSlice를 RTK API에서 가져온다.

 

- Slice를 생성하려면 Slice를 식별하기 위한 1️⃣ 문자열 이름 2️⃣초기 상태값  3️⃣ 상태 업데이트 방법을 정의하는 하나 이상의 Reducer함수 가 필요하다.

 

- Slice가 생성되면 생성된 4️⃣ Redux 액션 생성자와 5️⃣전체 Slice에 대한 리듀서 기능을 내보낼 수 있다.  

 

 

 

4. 다시 Store.js

import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'

export const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
})

- counterReducer 가져와서 Store에 추가한다.

- reducer 스토어에 이 Slice Reducer기능을 사용하여 해당 상태에 대한 모든 업데이트를 처리하도록 지시한다.

 

 

5. 사용할 파일 

import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './counterSlice'

export function Counter() {
  const count = useSelector((state) => state.counter.value)  // ❤️1️⃣
  const dispatch = useDispatch()

  return (
    <div>
      <div>
        <button
          aria-label="Increment value"
          onClick={() => dispatch(increment())}  //❤️2️⃣
        >
          Increment
        </button>
        <span>{count}</span>
        <button
          aria-label="Decrement value"
          onClick={() => dispatch(decrement())}  //❤️3️⃣
        >
          Decrement
        </button>
      </div>
    </div>
  )
}

 

- 이제 여기서 증가, 감소 button을 클릭할때마다 해당 Redux작업이 store로 발송이 될 것이다.  // 2️⃣ 3️⃣

 

- counterSlice는 이 작업을 보고 상태를 업데이트 한다.

 

- <Couter>컴포넌트는 store의 새 상태값을 보고 새 데이터를 가지고와 다시 렌더링을 한다.   // 1️⃣ 

 

 

 

이렇게 Redux-Tookit의 사용방법과 예제를 통해 로직을 알아보았다! 

props를 통해 state를 관리하면서 불편함을 많이 느꼈는데 RTK를 적용시켜 코드를 짜봐야겠다 ^_^

 

 

 

참고자료 

 https://redux-toolkit.js.org/tutorials/quick-start

https://redux.js.org/tutorials/essentials/part-1-overview-concepts

http://blog.hwahae.co.kr/all/tech/tech-tech/6946/