redux-toolkit

RumbleBi·2023년 6월 14일
0

Redux

목록 보기
1/1

이전에 사용했던 Redux는 기초적인 부분만 활용하였기 때문에 비동기처리를 도와주는 redux-saga, Redux를 더 편리하게 사용할 수 있는 redux-toolkit을 활용하여 진행하였다.

왜 redux-toolkit을 쓰는가

기존 redux 라이브러리로 상태관리를 하게 되면 몇 가지 문제가 있었다.

  1. 프로젝트의 크기가 커지면 그만큼 관리해야할 상태들이 늘어난다. 여기서 모든 상태의 속성들을 유지할려면 계속해서 복사를 해야한다. 그러다 보면 reducer 함수가 점점 커지게 되고, 가독성이 저하되고 보일러 플레이트의 크기도 매우 커질 것이다.

  2. 상태를 직접 변경하지 않고 항상 새로운 상태의 snapshot을 반환해야 한다. 그리고 이미 존재하는 상태를 함부로 바꿀 수 없다. 하지만 프로젝트의 크기가 커지면 중첩된 객체 및 배열에 있어 복잡한 데이터를 가지게 될 때, 실수로 데이터를 변경하게 된다면?

이러한 기존에 있는 문제들에 있어 해결책은 있다.

상수를 설정하여 오타를 방지할 수 있고, 리듀서들을 잘게 쪼개서 한 리듀서에 너무 많은 것들이 들어가지 않도록 분리하는 방법도 있다. 또한 써드파티 라이브러리를 사용하여(immer.js, immutable.js) 자동으로 상태를 복사해서 실수로 상태를 바꾸지 않도록할 수 있다.

하지만 이러한 기존의 redux의 단점들을 보완한 redux-toolkit을 사용하게 된다면 더욱 간편하고 가독성좋은 코드를 작성할 수 있기 때문에 이번 기회에 연습해 보았다.

redux-toolkit

redux-toolkit 설치

npm install @reduxjs/toolkit

설치가 완료되면 만약 기존에 설치된 redux 라이브러리가 있으면 삭제해주자. 이미 redux-toolkit에 redux의 기능이 있으므로 필요가 없기 때문이다.

index.jsx

import React from "react";
import ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import "./index.css";
import App from "./App";
import store from "./store/index";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);

Provider를 import해서 App 컴포넌트를 감싸고 store를 연결해주면 된다.

src/store/index.js

import { createSlice, configureStore } from "@reduxjs/toolkit";

const initialState = { counter: 0, showCounter: true };

const reducerSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    increment(state) {
      state.counter++;
    },
    decrement(state) {
      state.counter--;
    },
    increase(state, action) {
      state.counter += action.payload; // payload는 고정된 key값
    },
    toggleCounter(state) {
      state.showCounter = !state.showCounter;
    },
  },
});

const store = configureStore({ reducer: { counter: reducerSlice.reducer } });

export const counterActions = reducerSlice.actions;

export default store;

그리고 store 디렉토리에 index.js 파일을 생성하여 간단한 counter 상태를 관리하는 코드를 작성하였다.

여기서 기존 redux와는 다른 부분들이 몇가지 있다.

1. configureStore

기존에는 createStore 를 사용했지만 redux-toolkit에서는 configureStore로 변경되었다. createStore는 추후 deprecated 될 예정이기 때문에 사용하지 않는다.

2. createSlice

같은 역할을 하는 createReducer도 있지만, 코드 작성이 더 간단하고 가독성이 뛰어나다. 왜냐하면 액션 생성자 함수들과 해당 리듀서의 액션 핸들러가 자동으로 생성되기 때문이다. 그리고 기존 redux에서 reducer를 선언하면서 return 객체 형태로 반환하면서 작성해야 되는 코드들이 길어졌지만 createSlice를 사용함으로써 작성해야 되는 코드의 양이 줄어들고 더 직관적으로 변하였다.

src/components/Counter.js

import classes from "./Counter.module.css";
import { useSelector, useDispatch } from "react-redux";
import { counterActions } from "../store";

const Counter = () => {
  const dispatch = useDispatch();
  const counter = useSelector((state) => state.counter);
  console.log(counter);

  const incrementHandler = () => {
    dispatch(counterActions.increment());
  };

  const increaseHandler = () => {
    dispatch(counterActions.increase(10));
  };

  const decrementHandler = () => {
    dispatch(counterActions.decrement());
  };

  const toggleCounterHandler = () => {
    dispatch(counterActions.toggleCounter());
  };

  return (
    <main className={classes.counter}>
      <h1>Redux Counter</h1>
      {counter.showCounter && <div className={classes.value}>{counter.counter}</div>}
      <div>
        <button onClick={incrementHandler}>+</button>
        <button onClick={increaseHandler}>+10</button>
        <button onClick={decrementHandler}>-</button>
      </div>
      <button onClick={toggleCounterHandler}>Toggle Counter</button>
    </main>
  );
};

export default Counter;

기존 redux의 방식으로 dispatch를 할려면

dispatch({ type: "increase", amount: 10 });

과 같은 방식으로 타입이나 페이로드를 지정해줘야 하지만 toolkit을 사용한 dispatch는

counterActions.increment()

index.js에서 선언한 counterActios를 받아 사용하게 된다.

export const counterActions = reducerSlice.actions;
profile
기억보다는 기록하는 개발자

0개의 댓글