Redux Toolkit이란?
리액트 개발자라면 리덕스에 대해서 들어봤을 것이다.
리덕스란 자바스크립트 앱의 state 컨테이너로 1) 앱이 일관되게 동작하도록 하고, 2) 중앙화되어 있으며, 3) state가 언제, 어디서, 왜, 어떻게 바뀌었는지 등을 쉽게 디버깅할 수 있게 해주며, 4) 어떤 UI 계층과도 잘 동작하는 등 플렉시블하다.
리액트 프로젝트에서는 React Redux를 사용하는데, 사용법은 리액트 훅의 useReducer를 이해하고 있다면 dispatch, reducer, action, payload 등 비슷하게 동작한다고 생각하면 된다.
(useReducer에 대해 더 알고 싶다면 이 글을 참고)
리덕스를 사용하면 state를 관리하기 편하지만 수많은 boilerplate 코드를 작성해야한다는 점에서 불편한 점이 있었다.
리덕스 툴킷(Redux Toolkit)이란 이러한 boilerplate 코드가 많은 문제나 리덕스 store를 구성하는 것이 복잡한 문제 등 기존의 리덕스의 문제를 해결하고 유용한 패키지를 디폴트로 포함한 것이라고 생각하면 된다.
Redux와 Redux Toolkit의 차이점
그렇다면 Redux Toolkit이 기존 Redux보다 어떤 점이 다르고 편리한지 자세히 알아보기 위해 간단한 Counter 프로젝트(숫자를 더하고 빼는)를 만든다고 가정해보자.
기존의 Redux로는 아래와 같이 구현할 수 있다.
import { createStore } from 'redux';
const reducer = (state = { counter: 0 }, action) => {
switch(action.type) {
case 'increment':
return { counter: state.counter + 1 }
case 'decrement':
return { counter: state.counter - 1 }
default:
return state
}
}
const store = createStore(reducer);
export default store;
// App.jsx
import { useSelector, useDispatch } from 'react-redux'
function App() {
const counter = useSelector((state) => state.counter);
const dispatch = useDispatch();
const increment = () => {
dispatch({ type: 'increment' })
}
const decrement = () => {
dispatch({ type: 'decrement' })
}
// ...
}
export default App
이런 경우 reducer를 구현할 때마다 type 이름을 명확하게 적도록 해야하고 (혹은 ACTIONS 를 정의해 수동으로 type을 입력하는 것을 방지하는 방법도 있다.), switch문이나 if/else를 사용해야 하는 등 boilerplate 코드가 많다.
이제 같은 프로젝트를 Redux toolkit을 사용해서 Redux store를 구성해보자
// store/counterSlice.js
import { createSlice } from '@reduxjs/toolkit'
const initialState = {
value: 0,
}
export const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
state.value += 1
},
decrement: (state) => {
state.value -= 1
}
},
})
export const { increment, decrement } = counterSlice.actions
export default counterSlice.reducer
// store.js
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './counterSlice'
export const store = configureStore({
reducer: {
counter: counterReducer,
},
})
// App.js
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './store/counterSlice'
export function Counter() {
const count = useSelector((state) => state.counter.value)
const dispatch = useDispatch()
return (
<div>
<div>
<button
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
Increment
</button>
<span>{count}</span>
<button
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
Decrement
</button>
</div>
</div>
)
}
위 코드를 바탕으로 Redux와 Redux toolkit 차이점을 알아보자.
1. Dispatch
가장 크게 주목할 점은 기존 Redux에서는 dispatch를 할 때 아래와 같이 action type과 payload를 전달했던 것과 달리
dispatch({ type: ACTIONS.ADD, payload: { value: 5 }})
Redux toolkit에서는 코드를 더욱 간단하게 구현할 수 있다.
dispatch(add(5))
2. Reduc store 구성
configureStore()
을 사용해 Redux store를 간단하게 구성할수 있다.
3. Reducer
Redux toolkit은 기존의 Redux와는 다르게 reducer에 "mutating" 로직을 작성하는 것을 허용한다.
이는 Immer 라이브러리를 사용하기 때문인데, 실제로 state를 변형하는 것이 아니라 기존 state에 대한 변경을 감지하고 변경 상태를 바탕으로 완전히 새로운 immutable state를 생성한다.
4. Action
각 reducer 함수에 따라 Action creator가 자동으로 생성된다.
React 에서 Redux toolkit 사용해보기
기존 React 앱에서 Redux toolkit을 사용하기 위해서 패키지를 설치해줘도 되고
npm install @reduxjs/toolkit react-redux
Create React App에서 Redux 예시를 바로 만들어볼 수도 있다.
npx create-react-app my-app --template redux
다음 글에서 Redux Toolkit의 API에 대해 더 자세히 알아보자.
Reference
'개발 > 프론트엔드 (JS & React)' 카테고리의 다른 글
[Redux Toolkit] 3 - 리덕스 툴킷에서 타입스크립트 사용하기 (0) | 2022.11.14 |
---|---|
[Redux toolkit] 2 - Slice, Reducer, Action, Thunk란? (0) | 2022.11.11 |
[React + MongoDB + Netlify] Netlify Serverless 함수와 몽고DB를 사용해 리액트 프로젝트 무료로 호스팅하기 2 (0) | 2022.11.09 |
[React + MongoDB + Netlify] Netlify Serverless 함수와 몽고DB를 사용해 리액트 프로젝트 무료로 호스팅하기 1 (0) | 2022.11.08 |
[React & Storybook] 3 - 타입스크립트로 스토리 작성하기 (0) | 2022.09.29 |