React 전역 상태 관리 : Redux Toolkit

코딩로그·2025년 2월 26일

Redux Toolkit(RTK)

  • Redux를 더 쉽고 직관적으로 사용할 수 있도록 개선한 공식 라이브러리
  • Redux에서 반복적인 코드(boilerplate)를 줄이고, 비동기 작업을 간편하게 처리할 수 있도록 지원
  • 비동기 처리 (Thunk, API 호출 등)를 더욱 간편하게 관리 가능
  • Redux 공식 문서에서도 RTK 사용을 권장

필요한 모듈 설치

npm install @reduxjs/toolkit react-redux

Redux Toolkit vs 기존 Redux 비교

기능기존 ReduxRedux Toolkit
Action 관리직접 생성createSlice()에서 자동 생성
Reducer 관리combineReducers()createSlice()에서 통합
Store 생성createStore()configureStore()
미들웨어 추가applyMiddleware() 사용configureStore()에서 자동 포함
비동기 작업Redux-Thunk 사용createAsyncThunk() 제공

Redux Toolkit 사용법

1️⃣ createSlice()로 Reducer 및 Action 생성

Redux에서는 Action, Reducer, Action Creator를 각각 만들어야 했지만,
Redux Toolkit의 createSlice()를 사용하면 한 번에 정의할 수 있음

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;
  • reducers 객체 안에서 직접 상태를 변경 가능
  • counterSlice.actions에서 자동으로 액션 생성자(increment, decrement)가 생성됨
  • counterSlice.reducer리듀서 함수 역할을 함

2️⃣ configureStore()로 Store 생성

configureStore()를 사용하여 전역 상태 저장소 생성

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

export const store = configureStore({
  reducer: {
    counter: counterReducer,
  }
});
  • combineReducers()를 사용할 필요 없이 자동으로 여러 Reducer를 통합
const store = configureStore ({
	reducer : {
		counter : counterSlice.reducer,
		any : anySlice.reducer,
		... ...
	}
})

3️⃣ Redux Store를 Provider로 React에 연결

React와 Redux Store를 연결하는 방식은 동일
Provider로 감싸서 상태를 전역적으로 사용할 수 있도록 설정

import App, { store } from './App.jsx';
import { Provider } from 'react-redux';

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

4️⃣ useSelectoruseDispatch 사용

상태를 가져오고 변경하는 방식은 기존 Redux와 동일

useSelector를 사용해 상태값 가져오기

import { useSelector } from 'react-redux';

function App() {
  const counter = useSelector(state => state.counter);

  return (
    <>
      <div>counter : {counter}</div>
      <button>+</button>
      <button>-</button>
    </>
  );
}

useDispatch를 사용해 상태 변경하기

import { useDispatch } from 'react-redux';

function App() {
  const dispatch = useDispatch();

  return (
    <>
      <button onClick={() => dispatch(counterSlice.actions.increment())}>+</button>
      <button onClick={() => dispatch(counterSlice.actions.decrement())}>-</button>
    </>
  );
}

📌 비동기 작업 (Thunk) - createAsyncThunk()

Redux Toolkit에서 비동기 API 호출 등을 처리하기 위해 createAsyncThunk()를 사용

1️⃣ 비동기 Thunk 액션 생성

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

export const slowIncrementThunk = createAsyncThunk(
  'counter/slowIncrement',  // 액션 타입
  async (_, { dispatch }) => {  // 비동기 함수 실행
    setTimeout(() => {
      dispatch(counterSlice.actions.increment()); // 1초 후 증가
    }, 1000);
  }
);

2️⃣ 비동기 Thunk 액션을 Redux에 연결

import { configureStore } from '@reduxjs/toolkit';
import counterReducer, { slowIncrementThunk } from './counterSlice';

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

3️⃣ Thunk 액션을 컴포넌트에서 실행

import { useSelector, useDispatch } from 'react-redux';
import { slowIncrementThunk } from './counterSlice';

function App() {
  const counter = useSelector(state => state.counter);
  const dispatch = useDispatch();

  return (
    <>
      <h2>Slow Counter</h2>
      <div>Counter : {counter}</div>
      <button onClick={() => dispatch(slowIncrementThunk())}>1초 후 증가</button>
      <button onClick={() => dispatch(counterSlice.actions.decrement())}>-</button>
    </>
  );
}

Thunk 실행 흐름

  1. onClick 이벤트 발생 시 비동기 액션(dispatch) 실행
  2. setTimeout()이 1초 후 실행되면서 dispatch(counterSlice.actions.increment()) 실행
  3. counter 상태가 1 증가

profile
hello world!

0개의 댓글