Redux Toolkit과 React Query로 앱 성능 최적화

앱 성능 향상을 위한 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의 협업이 필수적임