리덕스 라이브러리를 통한 상태 관리를 할 경우에 리덕스의 store는 새로고침을 할 경우 state가 사라지게 됩니다.
이때 대응 방안으로 localStroage 등에 저장하여 새로고침을 하여도 저장공간에 있는 데이터를 redux에 불러오도록 하여 기존의 상태를 유지하도록 할 수 있습니다.
위에서 말한 작동을 위해 redux-persist를 사용하면 보다 쉽게 스토리지를 통한 관리를 할 수 있습니다.
기존 리덕스가 적용된 파일을 통해 구현하겠습니다.
$npm install redux-persist
기존 리덕스에 적용된 프로젝트에 redux-persist
라이브러리를 설치합니다.
기존 index.js
에는 Provider
가 추가되어있습니다. 기존 Provider
에 import { PersistGate } from "redux-persist/integration/react";
추가하여 PersistGate
를 통해App을 감싸줍니다.
store에서 기존에 가져오던 store 뿐 아니라 추가되는 persistor
도 가져와 PersistGate
에 persistor
로 props로 넘겨줍니다.
기존 리덕스나 리덕수 툴킷이나 적용 방법은 동일합니다.
// src/index.js
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import App from "App";
import { store, persistor } from "store"; // 기존 리덕스
import { store, persistor } from "app/store"; // 리덕스 툴킷
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
import storage from 'redux-persist/lib/storage
import storageSession from 'redux-persist/lib/storage/session
예제에는 localStorage
에 저장하겠습니다.
const persistConfig = {
key: "root",
// localStorage에 저장합니다.
storage: storage,
// 여러개의 reducer 중에 todo reducer만 localstorage에 저장합니다.
whitelist: ["todo"],
// blacklist -> 그것만 제외합니다
};
persist를 적용하기 앞서 스토리지에 저장하고자 하는 내역에 대해 설정할 수 있습니다.
config의 객체에는 key, storage, whitelist, blacklist 등이 존재하며 key(스토리지에서 사용되는 키 명칭), storage(localStorage, sessionStorage)는 필수로 입력해야하는 arguments이며 나머지는 선택에 따라서 입력합니다.
whitelist, blacklist는 whitelist 는 스토리지를 통해 관리할 항목이며 반대로 blacklist 는 스토리지로 관리하지 않을 항목을 나타냅니다.
// store/index.js
import { createStore } from "redux";
import { persistReducer, persistStore } from "redux-persist";
import storage from "redux-persist/lib/storage";
import { composeWithDevTools } from "redux-devtools-extension";
import rootReducer from "store/reducers";
const persistConfig = {
key: "root",
// localStorage에 저장합니다.
storage: storage,
// 여러개의 reducer 중에 todo reducer만 localstorage에 저장합니다.
whitelist: ["todo"],
// blacklist -> 그것만 제외합니다
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = createStore(persistedReducer, composeWithDevTools());
export const persistor = persistStore(store);
persistReducer(persistConfig, rootReducer)
를 통해 리듀서를 persist를 리듀서에 적용했다면 적용한 리듀서를 스토어로 만들고 만들어진 스토어를 persistStore(store)
를 통해 persistor
를 만들어줍니다.
여기서 만들어준 persistor
는 PersistGate
를 통해 App에 적용됩니다.
리덕스 툴킷의 경우 기존의 combineReducers
를 통해 따로 rootReducer
을 만들어 준후 기존의 리덕스에서 적용하던 방식대로 persistReducer
로 감싸줍니다.
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import { persistReducer, persistStore } from "redux-persist";
import storage from "redux-persist/lib/storage";
import todoSlice from "features/todo/todoSlice";
const persistConfig = {
key: "root",
// localStorage에 저장합니다.
storage: storage,
// 여러개의 reducer 중에 todo reducer만 localstorage에 저장합니다.
whitelist: ["todo"],
// blacklist -> 그것만 제외합니다
};
const rootReducer = combineReducers({ todo: todoSlice });
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = configureStore({
reducer: persistedReducer,
});
export const persistor = persistStore(store);
그렇게 하여 실행 할 경우 콘솔창에 아래와 같은 에러창이 발생하게 됩니다.
해당 에러는 리덕스 툴킷에서 기본적으로 직렬화할 경우 데이터의 유실이 발생을 방지하기 위해 뜨는 에러 로그입니다.
아래의 1, 2번 방법으로 직렬화 체크를 막음으로써 에러 로그가 나타나지 않도록 할 수 있으며 1번 방법의 경우 공식문서에서 제공된 방법으로 1번 방법을 추천합니다.
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import { persistReducer, persistStore } from "redux-persist";
1. import { FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER } from "redux-persist";
import storage from "redux-persist/lib/storage";
import todoSlice from "features/todo/todoSlice";
const persistConfig = {
key: "root",
// localStorage에 저장합니다.
storage: storage,
// 여러개의 reducer 중에 todo reducer만 localstorage에 저장합니다.
whitelist: ["todo"],
// blacklist -> 그것만 제외합니다
};
const rootReducer = combineReducers({ todo: todoSlice });
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = configureStore({
reducer: persistedReducer,
1. middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
2. middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false,
}),
});
export const persistor = persistStore(store);
npm redux-persist
https://www.npmjs.com/package/redux-persist
리덕스 툴킷 사용 가이드(redux-persist)
https://redux-toolkit.js.org/usage/usage-guide#use-with-redux-persist
👉 깃허브를 통해 확인할 수 있습니다.
https://github.com/kim-gunwoo/redux-exam