앱 성능 향상을 위한 Redux Toolkit과 React Query의 조합
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
웹 개발
대상자
- 대상자: 대규모 React 앱 개발자, 상태 관리 및 성능 최적화에 관심 있는 개발자
- 난이도: 중급 이상 (Redux Toolkit, React Query 이해 필요)
핵심 요약
- Redux Toolkit은 앱의 장기 기억으로, 사용자 설정, UI 상태, 비즈니스 로직을 관리
- React Query는 단기 기억으로, 서버 데이터의 유효성 확인 및 캐싱을 통해 불필요한 리렌더링 감소
- 실적: 60% 리렌더링 감소, 30% 서버 비용 절감, 새 개발자 온보딩 시간 2주 → 3일
섹션별 세부 요약
1. 문제 상황
- 상황: 대규모 앱에서 Context API 사용 시 불필요한 리렌더링 발생 (예: 검색창 입력 시 전체 목록 리렌더링)
- 결과: 성능 저하, 사용자 불만 증가, 개발자 생산성 감소
2. Redux Toolkit과 React Query의 역할
- Redux Toolkit:
- 장기 상태 관리 (사용자 권한, UI 상태 등)
- 비동기 작업 처리 (createAsyncThunk
, extraReducers
활용)
- React Query:
- 데이터 캐싱 및 자동 재검증 (staleTime
, cacheTime
설정)
- 에러 핸들링 (404 응답 시 재시도 방지)
3. 구현 예시 (Next.js 15.3.3 기준)
- store.ts:
```ts
export const makeStore = () => {
const store = configureStore({
reducer: {
auth: authSlice.reducer,
ui: uiSlice.reducer,
api: apiSlice.reducer,
},
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(apiSlice.middleware),
})
setupListeners(store.dispatch)
return store
}
```
- StoreProvider.tsx:
```tsx
export default function StoreProvider({ children }) {
const storeRef = useRef
const queryClientRef = useRef
if (!storeRef.current) {
storeRef.current = makeStore()
queryClientRef.current = new QueryClient({
defaultOptions: {
queries: {
staleTime: 60 * 1000, // 1분
retry: (failureCount, error) => error.status !== 404 && failureCount < 3,
},
},
})
}
return (
{children}
{process.env.NODE_ENV === 'development' &&
)
}
```
4. authSlice 예시
- 인증 로직:
```ts
export const authenticateUser = createAsyncThunk(
'auth/authenticate',
async (credentials, { rejectWithValue }) => {
try {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(credentials),
})
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
throw new Error(errorData.message || '인증 실패')
}
const data = await response.json()
const expiryTime = Date.now() + (data.expiresIn * 1000)
localStorage.setItem('token', data.token)
localStorage.setItem('sessionExpiry', expiryTime.toString())
return { ...data, sessionExpiry: expiryTime }
} catch (error) {
return rejectWithValue(error instanceof Error ? error.message : '알 수 없는 오류')
}
}
)
```
결론
- 핵심 팁: Redux Toolkit과 React Query를 결합하여 불필요한 리렌더링 방지 및 데이터 캐싱 최적화 수행
- 권장사항:
staleTime
,cacheTime
값을 실제 데이터 변화 주기에 맞게 설정,devTools
는 개발 환경에서만 활성화 - 결론: 성능 문제 해결을 위해 Redux Toolkit과 React Query의 협업이 필수적임