반응형
✅ 1. useAppSelector, useAppDispatch (타입 안전한 Hooks)
Redux를 사용할 때 타입을 명시적으로 설정하면 더 안전하게 사용할 수 있습니다.
// src/app/hooks.ts
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './store'
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
그리고 기존 useSelector, useDispatch 대신 다음과 같이 사용합니다:
const dispatch = useAppDispatch()
const count = useAppSelector((state) => state.counter.value)
✅ 2. 비동기 Thunk (createAsyncThunk)
API 요청을 Redux 상태로 관리하려면 createAsyncThunk를 사용합니다.
// src/features/counter/counterSlice.ts
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
// 비동기 thunk 생성
export const fetchCount = createAsyncThunk(
'counter/fetchCount',
async (amount: number) => {
const res = await fetch(`https://api.example.com/count?amount=${amount}`)
const data = await res.json()
return data.count as number
}
)
interface CounterState {
value: number
loading: boolean
}
const initialState: CounterState = {
value: 0,
loading: false,
}
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchCount.pending, (state) => {
state.loading = true
})
.addCase(fetchCount.fulfilled, (state, action) => {
state.value = action.payload
state.loading = false
})
.addCase(fetchCount.rejected, (state) => {
state.loading = false
})
},
})
✅ 3. Redux Persist (데이터 로컬 저장)
앱을 새로고침해도 Redux 상태가 유지되도록 하려면 redux-persist를 사용합니다.
설치
npm install redux-persist
설정
// src/app/store.ts
import { configureStore } from '@reduxjs/toolkit'
import { persistStore, persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import counterReducer from '../features/counter/counterSlice'
import { combineReducers } from 'redux'
const rootReducer = combineReducers({
counter: counterReducer,
})
const persistConfig = {
key: 'root',
storage,
}
const persistedReducer = persistReducer(persistConfig, rootReducer)
export const store = configureStore({
reducer: persistedReducer,
})
export const persistor = persistStore(store)
index.tsx 연결
import { PersistGate } from 'redux-persist/integration/react'
import { store, persistor } from './app/store'
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
✅ 4. 모듈화 구조 (기능 단위 구조)
기능별 디렉토리로 구성해 유지 보수를 쉽게 할 수 있습니다.
src/
├── app/
│ ├── store.ts
│ └── hooks.ts
├── features/
│ ├── counter/
│ │ ├── counterSlice.ts
│ │ └── Counter.tsx
│ └── user/
│ ├── userSlice.ts
│ └── UserInfo.tsx
각 슬라이스는 독립적으로 관리하며 store.ts에서 한 번에 조합:
import userReducer from '../features/user/userSlice'
import counterReducer from '../features/counter/counterSlice'
const rootReducer = combineReducers({
user: userReducer,
counter: counterReducer,
})
정리 요약
useAppSelector, useAppDispatch | 타입 안정성 강화 |
createAsyncThunk | API 비동기 요청 처리 |
redux-persist | 새로고침에도 상태 유지 |
모듈화 구조 | 기능별 폴더로 관리 |
728x90
반응형
'웹개발 > reactjs' 카테고리의 다른 글
Redux VS Zustand 차이점 (0) | 2025.04.19 |
---|---|
Redux + TypeScript 확장 개념 완전 이해하기 (0) | 2025.04.14 |
Redux + typescript : 카운터 증가/감소를 구현 (0) | 2025.04.14 |
React에서 타입스크립트 사용 (0) | 2025.04.14 |
React + TypeScript에서 이벤트(Event) (1) | 2025.04.14 |