[TIL] Redux Toolkit(RTK)

기성·2024년 8월 23일
0

TIL

목록 보기
44/81
post-thumbnail

Redux

Redux는 우리가 잘 알다 시피 전역 상태 관리 라이브러리이다. 말 그대로 전역에서 상태를 관리 할 수 있게 도와주는 라이브러리이다.

그림을 통해 Redux의 진행을 확인할 수 있다. 단방향으로의 관리가 이뤄지는 것을 알 수 있다.
우리는 Redux를 통해 전역 상태 관리를 할 수 있지만 너무 어렵다. 왜? 쓸 코드가 너무나 많다.
사용하기 위해서는 rootReducer를 정의하면서 combineReducer를 사용해야하고

// reducers/index.js

import { combineReducers } from "redux";
import todos from "./todos";

const rootReducer = combineReducers({
  todos,
});

export default rootReducer;

합칠 리듀서들을 위한 세부 Reducer들을 정의해야하고

// reducers/todos.js

export const ADD_TODO = "TODO/ADD_TODO";
export const REMOVE_TODO = "TODO/REMOVE_TODO";
export const TOGGLE_TODO = "TODO/TOGGLE_TODO";

export const addTodo = (text) => ({ type: ADD_TODO, text });
export const removeTodo = (id) => ({ type: REMOVE_TODO, id });
export const toggleTodo = (id) => ({ type: TOGGLE_TODO, id });

const initialState = {
  todos: [],
};

const todos = (state = initialState, action) => {
  switch (action.type) {
    case ADD_TODO:
      return {
        ...state,
        todos: [
          ...state.todos,
          { id: Date.now(), text: action.text, completed: false },
        ],
      };
    case REMOVE_TODO:
      return {
        ...state,
        todos: state.todos.filter((todo) => todo.id !== action.id),
      };
    case TOGGLE_TODO:
      return {
        ...state,
        todos: state.todos.map((todo) =>
          todo.id === action.id ? { ...todo, completed: !todo.completed } : todo
        ),
      };
    default:
      return state;
  }
};

export default todos;

store도 만들고

// store/index.js

import { createStore } from "redux";
import rootReducer from "../reducers";

const store = createStore(
  rootReducer,
);

export default store;

App에 store를 제공해주기까지 해야하는데

// index.js

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

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

컴포넌트에서 또 redux를 사용해야한다. 너무많다.

// components/TodoList.js

import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { addTodo, removeTodo, toggleTodo } from "../reducers/todos";

const TodoList = () => {
  const [input, setInput] = useState("");
  const todos = useSelector((state) => state.todos.todos);
  const dispatch = useDispatch();

  const handleAddTodo = () => {
    if (input.trim()) {
      dispatch(addTodo(input));
      setInput("");
    }
  };

  const handleRemoveTodo = (id) => {
    dispatch(removeTodo(id));
  };

  const handleToggleTodo = (id) => {
    dispatch(toggleTodo(id));
  };

  return (
    <div>
      <h1>Todo List</h1>
      <input
        value={input}
        onChange={(e) => setInput(e.target.value)}
        placeholder="Add a new todo"
      />
      <button onClick={handleAddTodo}>Add</button>
      <ul>
        {todos.map((todo) => (
          <li key={todo.id} style={{ textDecoration: todo.completed ? "line-through" : "none" }}>
            <span onClick={() => handleToggleTodo(todo.id)}>{todo.text}</span>
            <button onClick={() => handleRemoveTodo(todo.id)}>Remove</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;

이를 해결하기 위해 나온것이 Redux Toolkit(RTK)이다.

Redux Toolkit(RTK)

RTK란 현재 Redux로직을 작성할 때 권장하는 방법으로, Redux의 복잡성을 줄이고 개발 효율성을 높이기 위해서 만들어졌다. 기본적으로 Redux의 코어 라이브러리를 포함하고 있어 별도의 설정없이 사용할 수 있다.
이제 똑같이 RTK로 TodoList를 만드는 로직을 보면 더 간단한 코드를 볼 수 있다.
1. createSlice를 통해 reducer와 action을 한번에 정의한다.

// features/todos/todosSlice.js

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

const todosSlice = createSlice({
  name: "todos",
  initialState: {
    todos: [],
  },
  reducers: {
    addTodo: (state, action) => {
      state.todos.push({
        id: crypto.randomUUID(),
        text: action.payload,
        completed: false,
      });
    },
    removeTodo: (state, action) => {
      state.todos = state.todos.filter((todo) => todo.id !== action.payload);
    },
    toggleTodo: (state, action) => {
      const todo = state.todos.find((todo) => todo.id === action.payload);
      if (todo) {
        todo.completed = !todo.completed;
      }
    },
  },
});

export const { addTodo, removeTodo, toggleTodo } = todosSlice.actions;
export default todosSlice.reducer;
  1. store를 설정한다.
// store/index.js

import { configureStore } from "@reduxjs/toolkit";
import todosReducer from "../features/todos/todosSlice";

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

export default store;
  1. App에 적용
// index.js

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

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);
  1. 컴포넌트에서 사용
import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { addTodo, removeTodo, toggleTodo } from "../features/todos/todosSlice";

const TodoList = () => {
  const [input, setInput] = useState("");
  const todos = useSelector((state) => state.todos.todos);
  const dispatch = useDispatch();

  const handleAddTodo = () => {
    dispatch(addTodo(input));
  };

  const handleRemoveTodo = (id) => {
    dispatch(removeTodo(id));
  };

  const handleToggleTodo = (id) => {
    dispatch(toggleTodo(id));
  };

  return (
    <div>
      <h1>Todo List</h1>
      <input
        value={input}
        onChange={(e) => setInput(e.target.value)}
        placeholder="Add a new todo"
      />
      <button onClick={handleAddTodo}>Add</button>
      <ul>
        {todos.map((todo) => (
          <li
            key={todo.id}
            style={{ textDecoration: todo.completed ? "line-through" : "none" }}
          >
            <span onClick={() => handleToggleTodo(todo.id)}>{todo.text}</span>
            <button onClick={() => handleRemoveTodo(todo.id)}>Remove</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoList;

확실히 action과 state를 관리하는 로직에서 간단, 간편해진것이 눈에 보인다.

그렇다면 이런 간편함 이외에 우리가 RTK를 사용하는 이유가 뭘까?

Redux Toolkit을 사용하는 이유

  1. 코드 간소화: RTK를 사용하면 기존의 복잡한 Redux 로직을 단순화할 수 있다.
  2. 불변성 관리: RTK는 Immer를 활용하여 불변성을 자동으로 관리한다. 개발자는 복잡한 spread 문법을 사용하지 않아도 상태를 업데이트할 수 있다.
  3. 기본 제공 기능: RTK는 Redux DevTools, thunk 미들웨어와 같은 필수 기능들을 기본적으로 포함하고 있다. 추가적인 설정 없이도 Redux 개발 환경을 최적화할 수 있다.

RTK 장점

  • 개발 시간 절약: 불필요한 보일러플레이트 코드 없이 효율적으로 Redux 로직을 작성할 수 있다.
  • 유지보수 용이성: 코드 구조가 더 간단해지며, 상태 관리 로직을 추적하기 쉽다.
  • Redux 의 장점 그대로: Redux Toolkit에는 최신 Redux 개발 패턴이 내장되어있기 때문에, Redux 의 Best Practice 를 자연스럽게 따르게 된다.

이렇기 때문에 우리는 Redux를 동작만 알고 있고 RTK를 통해서 Redux를 사용하면 되겠다~
처음엔 어렵지만 적응한다면 쉽게 전역상태관리를 할 수 있게 되지 않을까 생각하고 있다.

profile
프론트가 하고싶어요

0개의 댓글