[RTK]자주 쓰는 Redux Toolkit 기능
Redux Toolkit(RTK)은 Redux 공식팀에서 제공하는 상태관리 툴킷으로, 개발자들이 겪는 복잡한 설정과 보일러플레이트 문제를 해결해줍니다. 특히 현업에서 많이 쓰이는 기능을 잘 알고 있으면, 개발 생산성과 유지보수성이 모두 크게 향상됩니다.
이 글에서는 RTK에서 가장 자주 사용되는 기능 5가지를 실전 코드와 함께 자세히 소개합니다.
1. createSlice – 상태와 리듀서를 하나로 통합
createSlice는 RTK의 핵심 기능 중 하나로, 상태 초기값, 액션 생성, 리듀서를 하나의 선언형 코드로 관리할 수 있게 해줍니다. Redux의 대표적인 단점인 ‘액션 따로, 리듀서 따로’ 구조를 없애줍니다.
예시 코드
import { createSlice } from '@reduxjs/toolkit'
const counterSlice = createSlice({
name: 'counter',
initialState: { value: 0 },
reducers: {
increment: (state) => { state.value += 1 },
decrement: (state) => { state.value -= 1 },
incrementByAmount: (state, action) => {
state.value += action.payload
}
}
})
export const { increment, decrement, incrementByAmount } = counterSlice.actions
export default counterSlice.reducer
state.value += 1처럼 불변성 걱정 없이 코드를 작성할 수 있는 건 RTK 내부에 Immer가 기본 내장되어 있기 때문입니다.
2. createAsyncThunk – 비동기 요청과 상태를 동시에 관리
기존 Redux에서 비동기 요청을 다루기 위해선 Redux-thunk 또는 Redux-saga 등을 별도로 설정해야 했습니다.
하지만 RTK는 createAsyncThunk를 통해 비동기 API 호출과 상태 관리를 하나의 흐름으로 처리할 수 있습니다.
예시 코드
import { createAsyncThunk } from '@reduxjs/toolkit'
import axios from 'axios'
export const fetchUser = createAsyncThunk('user/fetchUser', async (userId) => {
const response = await axios.get(`/api/users/${userId}`)
return response.data
})
createAsyncThunk로 만들어진 액션은 자동으로 3단계 상태를 가집니다:
- pending: 요청 중
- fulfilled: 요청 성공
- rejected: 요청 실패
이를 extraReducers에서 다음과 같이 처리합니다:
extraReducers: (builder) => {
builder
.addCase(fetchUser.pending, (state) => {
state.status = 'loading'
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.status = 'succeeded'
state.user = action.payload
})
.addCase(fetchUser.rejected, (state, action) => {
state.status = 'failed'
state.error = action.error.message
})
}
3. createEntityAdapter – 리스트 상태를 효율적으로 관리
여러 개의 데이터를 리스트 형태로 관리할 때는 createEntityAdapter가 매우 유용합니다. 예를 들어, 사용자 목록, 게시판 글 리스트 등에서 다음과 같은 기능이 필요합니다:
- 데이터 정렬
- id 기반 조회
- 빠른 추가/삭제/수정
기능 예시
import { createEntityAdapter } from '@reduxjs/toolkit'
const usersAdapter = createEntityAdapter({
selectId: (user) => user.id,
sortComparer: (a, b) => a.name.localeCompare(b.name)
})
const initialState = usersAdapter.getInitialState({
loading: false
})
usersAdapter는 다음과 같은 메서드를 제공합니다:
- addOne, addMany, removeOne, updateOne
- selectAll, selectById 등 selector도 자동 생성
복잡한 리스트를 단순한 객체 조작처럼 다룰 수 있어, 실무에서 매우 자주 사용됩니다.
4. RTK Query (createApi) – 서버 상태를 자동으로 관리
RTK Query는 서버에서 데이터를 가져오고, 캐시하고, 리패치하고, 무효화하는 과정을 자동화해주는 기능입니다.
React Query와 유사하지만 Redux 상태와 자연스럽게 통합됩니다.
기능 요약
- API 요청을 캐시하고 자동으로 재요청
- useQuery, useMutation 훅 제공
- 요청 상태를 자동 관리 (isLoading, isError, data 등)
- 자동으로 re-fetch, cache invalidation 가능
예시 코드
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
export const userApi = createApi({
reducerPath: 'userApi',
baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
endpoints: (builder) => ({
getUser: builder.query({
query: (id) => `/users/${id}`
})
})
})
export const { useGetUserQuery } = userApi
이 기능만으로도 대부분의 서버 통신 로직을 간단하게 관리할 수 있습니다.