Front-End/Next.js

RTK(Redux Toolkit) : 비동기 상태관리부터 Axios와의 차이, 예제

봉의일상 2025. 5. 10. 20:43

 

Redux Toolkit(RTK)는 단순한 상태 저장소 이상의 기능을 제공하여, 비동기 요청의 상태 변화를 효율적으로 관리할 수 있습니다.
이 글에서는 RTK의 핵심 기능인 반응형 상태 처리 개념부터 Axios와의 차이점, 그리고 실전 코드 예제까지 한 번에 정리해드립니다.


RTK의 실시간 상태 처리란?

RTK는 다음 세 가지 상태를 자동으로 관리해 줍니다:

  • pending: 요청 중
  • fulfilled: 요청 성공
  • rejected: 요청 실패

이 상태를 기반으로 로딩 스피너, 에러 메시지, UI 갱신 등을 자동화할 수 있어, 아래와 같은 활용이 가능합니다.

 

활용 예시

  1. 채팅 메시지 수신: WebSocket 또는 polling으로 서버에서 메시지를 받아 상태 갱신
  2. 주문 상태 추적: 배송 상태에 따라 UI를 동적으로 변경
  3. 파일 업로드 진행률: 업로드 상태 및 진행률 표시
  4. 알림 센터 구현: 미확인 알림 상태 추적 및 UI 반영

Axios와 RTK 비교

항목 Axios RTK
목적 HTTP 요청 처리 상태관리 + 비동기 통합
상태관리 직접 구현해야 함 자동 제공
로딩/에러 처리 수동 처리 내장 상태로 가능
중앙 상태 공유 Redux 등 필요 Redux store 통합
코드 구조 자유도 높음 공식 구조 권장
DevTools 직접 설정 필요 자동 통합
 

Axios는 네트워크 요청만 처리하고 상태는 별도 관리가 필요합니다.
반면 RTK는 요청과 상태, 흐름을 Redux 아키텍처 안에서 일관되게 처리할 수 있다는 점이 큰 장점입니다.


RTK 사용법 (설정 및 코드 예시)

1. 패키지 설치

npm install @reduxjs/toolkit react-redux

 

2. Slice 생성

import { createSlice } from '@reduxjs/toolkit'

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

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

3. 비동기 Thunk 생성

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import axios from 'axios'

export const fetchUser = createAsyncThunk('user/fetch', async (userId) => {
  const res = await axios.get(`/api/user/${userId}`)
  return res.data
})

const userSlice = createSlice({
  name: 'user',
  initialState: { data: null, status: 'idle', error: null },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchUser.pending, (state) => { state.status = 'loading' })
      .addCase(fetchUser.fulfilled, (state, action) => {
        state.status = 'succeeded'
        state.data = action.payload
      })
      .addCase(fetchUser.rejected, (state, action) => {
        state.status = 'failed'
        state.error = action.error.message
      })
  }
})

export default userSlice.reducer
 

4. Store 설정

import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counterSlice'
import userReducer from '../features/userSlice'

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

5. Provider 설정

 
import { Provider } from 'react-redux'
import { store } from './app/store'

<Provider store={store}>
  <App />
</Provider>