250x250
Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Archives
Today
Total
관리 메뉴

y.developer

[TIL] Day 39 Redux Toolkit 간편하고 강력한 상태 관리 본문

카테고리 없음

[TIL] Day 39 Redux Toolkit 간편하고 강력한 상태 관리

y.developer 2023. 11. 28. 21:41
728x90

2023.11.28 월

 

순수 리덕스는 이제 잘 사용되지 않는 추세이다.

편의성을 갖춰 더 효율적인 방법으로 고안되어 탄생한 Redux Toolkit을 주로 사용한다.
Redux Toolkit은 Redux를 더욱 효과적으로 사용할 수 있게 도와준다.

이를 통해 간단하고 강력한 API를 제공하여 Redux 코드의 생산성을 높이고 반복적인 작업을 줄일 수 있다.

Redux Toolkit에 대해서 알아보자!


Redux Toolkit

리덕스 툴킷은 우리가 이전에 배운 리덕스를 개량한 것으로 생각된다.

리덕스를 사용하기 위해 작성했던 ducks 패턴의 요소들이 전체적인 코드의 양을 늘린다는 개발자들의 불만이 발생하기 시작했고, 리덕스 팀에서는 이것을 수용하여 코드는 더 적게, 그리고 리덕스를 더 편하게 쓰기 위한 기능들을 흡수해서 만든 것이 리덕스툴킷이다. 줄여서 RTK 라고도 한다.

 

리덕스 툴킷은 우리가 배웠던 리덕스와 구조나 패러다임이 모두 똑같다. 즉 새로운 것이 아니다.

리덕스의 전체 코드의 양을 줄이기 위해 새로운 API가 추가되었고 우리가 일일히 손으로 만들어 줘야 했던 ducks 패턴의 요소들이 어느정도 자동화 되었다.

컴포넌트에서 useSelector를 통해서 사용하는 것은 모두 똑같다. 바뀐 부분은 그저 모듈 파일 뿐이다. 이후 일반 리덕스와 툴킷의 요소를 비교해서 어떤 식으로 바뀌었는지 살펴보려고 한다.

 

 

1. configureStore

configureStore 함수는 Redux Toolkit에서 제공하는 함수로, Redux 스토어를 설정하는 과정을 간소화하여 관리할 수 있게 만들어준다.

reducer  middleware 설정을 쉽게 구성할 수 있게 해주며, 개발 중에는 Redux DevTools Extension을 자동으로 설정하여 스토어의 상태와 액션을 쉽게 추적할 수 있다.

Immer를 활용하여 불변성을 관리하며, 미들웨어의 향상된 커스터마이징을 지원하여 Redux 애플리케이션을 효율적으로 구축하고 유지보수할 수 있게 도와준다.

이를 통해 개발자는 더 간단하고 효율적으로 Redux를 활용할 수 있다.

 

import { configureStore } from '@reduxjs/toolkit';

const store = configureStore({
  reducer: {
    // reducers...
  },
});

 


2. createSlice

createSlice 함수는 Redux Toolkit에서 제공하는 유틸리티 중 하나로, Redux 리듀서와 관련 액션들을 한 번에 생성할 수 있는 편리한 방법을 제공한다.

초기 상태, 리듀서 함수, 그리고 관련된 액션 생성자들을 하나의 객체로 정의할 수 있다. 또한 Immer 라이브러리를 내부적으로 활용하여 간편한 불변성 관리를 지원하며, 액션들의 타입 문자열과 액션 생성자 함수를 자동으로 생성하여 반복적이고 번거로운 작업을 최소화한다.

이를 통해 Redux 애플리케이션을 보다 반복적인 작업을 줄여주어 코드를 더 간결하게 작성할 수 있고, 코드의 가독성과 유지보수성을 향상시킬 수 있다.

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

const counterSlice = createSlice({
  name: 'counter',
  initialState: 0,
  reducers: {
    increment: state => state + 1,
    decrement: state => state - 1,
  },
});

export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;

 


3. createAsyncThunk

createAsyncThunk은 비동기 작업을 효과적으로 처리하기 위해서 만들어졌다.

비동기 작업에 대한 성공, 실패, 혹은 진행 중인 상태에 따라 자동으로 액션을 생성할 수 있고, 간단하게 정의하여 관리할 수 있다.

이를 통해 개발자는 보일러플레이트 코드를 줄이고, 비동기 작업에 관련된 리듀서 및 액션들을 효율적으로 관리할 수 있다.

import { createAsyncThunk } from '@reduxjs/toolkit';
import api from 'api'; // 실제 API 모듈

export const fetchUser = createAsyncThunk('user/fetchUser', async (userId) => {
  const response = await api.fetchUser(userId);
  return response.data;
});

 

 

코드 적용

순수 reduxredux-toolkit

순수 redux로 작성했던 TodoList를 redux-toolkit의 형식에 맞게 변환해보면서 어떤 점이 편리한지 비교해보았다.

 

configStore.js

src / redux / config / configStore.js

순수 redux

더보기
import { createStore } from "redux";
import { combineReducers } from "redux";
import todos from "../modules/todos";

const rootReducer = combineReducers({ todos });

const store = createStore(rootReducer);

export default store;

 

redux-toolkit

더보기
import todos from "../modules/todos";
import { configureStore } from "@reduxjs/toolkit";

const store = configureStore({
  reducer: {
    todos,
  },
});

export default store;

 

 

todos.js

src / redux / modules / todos.js

순수 redux

더보기
// import uuid from "react-uuid";
import shortid from "shortid";

const ADD_TODO = "ADD_TODO";
const DELETE_TODO = "DELETE_TODO";
const SWITCH_TODO = "SWITCH_TODO";

export const addTodo = (payload) => {
  return {
    type: ADD_TODO,
    payload,
  };
};

export const deleteTodo = (payload) => {
  return {
    type: DELETE_TODO,
    payload,
  };
};

export const switchTodo = (payload) => {
  return {
    type: SWITCH_TODO,
    payload,
  };
};

const initialState = [
  {
    id: shortid.generate(),
    title: "제목1",
    content: "내용1",
    isDone: false,
  },
  {
    id: shortid.generate(),
    title: "제목2",
    content: "내용2",
    isDone: true,
  },
];

// 리듀서
const todos = (state = initialState, action) => {
  switch (action.type) {
    case ADD_TODO:
      // payload = newTodo
      return [...state, action.payload];

    case DELETE_TODO:
      // payload = id
      return state.filter((item) => item.id !== action.payload);

    case SWITCH_TODO:
      // payload = id
      return state.map((item) => {
        if (item.id === action.payload) {
          return { ...item, isDone: !item.isDone };
        } else {
          return item;
        }
      });

    default:
      return state;
  }
};

export default todos;

 

redux-toolkit

더보기
// import uuid from "react-uuid";
import { createSlice } from "@reduxjs/toolkit";
import shortid from "shortid";

const initialState = [
  {
    id: shortid.generate(),
    title: "제목1",
    content: "내용1",
    isDone: false,
  },
  {
    id: shortid.generate(),
    title: "제목2",
    content: "내용2",
    isDone: true,
  },
];

const todosSlice = createSlice({
  name: "todos",
  initialState,
  reducers: {
    addTodo: (state, action) => {
      return [...state, action.payload];
    },
    deleteTodo: (state, action) => {
      return state.filter((item) => item.id !== action.payload);
    },
    switchTodo: (state, action) => {
      return state.map((item) => {
        if (item.id === action.payload) {
          return { ...item, isDone: !item.isDone };
        } else {
          return item;
        }
      });
    },
  },
});

export const { addTodo, deleteTodo, switchTodo } = todosSlice.actions;
export default todosSlice.reducer;

 

 

 


하루를 마치며

이전까지는 순수 redux를 배우며 기본적인 형태를 익혔다.

하지만 더 효율적인 코드를 작성하기 위해서, 앞으로의 트랜드를 반영하기 위해서라도 Redux Toolkit의 사용법을 익혀야겠다.

Redux Toolkit을 사용하면 Redux를 더 효율적으로 관리할 수 있으며, 코드의 길이도 줄일 수 있고, 이는 휴면에러도 방지하는데도 큰 도움이 된다.

또한 코드의 가독성을 높이고 개발 생산성을 향상시키는 데 크게 기여할 수 있다.

 

 

오늘의 한 줄
Redux가 발전하는 것처럼
나도 계속 발전하자




728x90