[Redux] redux-toolkit 사용시 redux-persist로 상태 유지하기, non-serializable 에러 해결

김뀨뀨·2023년 1월 30일
1

redux-persist 도입

프로젝트에서 상태관리 툴로 Redux, Redux-toolkit을 채택하고 유저 정보를 전역적인 state로 관리하기로 했다. (isLogin, 닉네임, 이메일 등)

그런데 Redux는 새로 고침을하면 저장되어있는 state가 없어지기 때문에 로그인 후 한번 저장하고 계속 사용해야하는 유저 정보를 붙잡아둘 필요가 있다.
이 때 사용하는 것이 redux-persist 이다.

redux-persist 사용법

이미 redux, redux-toolkit 세팅이 되어 있는 상태라면 할일이 많지는 않다.

npm install redux-persist

우선 패키지부터 설치해준다.

src/store/index.js 파일 전체 코드

persistConfig

const persistConfig = {
  key: 'root',
  storage, //local Storage에 저장
  whitelist: ['auth'], //auth Reducer만 저장
};

persist와 관련 설정을 지정해준다.
redux-persist는 local storage 또는 session storage에 데이터를 저장해두는데, 나는 로컬 스토리지로 지정해주었다.
whitelist는 state를 유지할 reducer를 지정한다. 반대로 blacklist를 지정할 수도 있다.

persistedReducer

const persistedReducer = persistReducer(persistConfig, rootReducer);

export const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: false,
    }),
});

알다시피 redux에서 최상위 rootReducer가 모든 reducer를 갖고있기 때문에 그 rootReducer를 persist되는 Reduce로 만들어준다.

그리고 store에 저장하는 reducer를 방금 만든 reducer로 지정해준다.

persistor

//src/index.js에서 PersistGate 사용을 위한 persistor
export const persistor = persistStore(store);

이 코드는 최상위 index.js 파일과 함께 보아야 한다.

index.js

persist store를 사용하기 위해 APP 컴포넌트를 PersistGate로 감싸주고 아까 정의한 persistor를 사용한다.

참고

지금은 auth Reducer 하나만 persist하는 간단한 상황이지만 reducer 안의 특정 state만 persist하고 싶거나, 반대의 상황 등 여러가지 상황이 생길 수 있는데 두번째 참고 링크에서 친절하게 알려주고 있다.

non-serializable 에러

위 코드에서 처음에 store의 middleware를 지정하지 않았을 때 콘솔창에 이러한 에러가 뜬다.
https://stackoverflow.com/questions/61704805/getting-an-error-a-non-serializable-value-was-detected-in-the-state-when-using

말 그대로 state에 non-serializable한 데이터가 있다는 상황인데 공식문서를 보면

  • redux의 사용 규칙 중 하나로 non-serializable한 데이터를 state나 action에 넣지 말라는 것이고,
  • serializability dev check middleware가 자동적으로 실행된다고 얘기하고 있다.

실수를 방지하기 위해 이 middleware가 실행되도록 냅두는 것이 권고사항이라고는 하지만, 끄는 방법도 함께 알려주고 있다.

방법 1) redux-tookit과 함께 사용하는 경우

import { combineReducers, configureStore } from '@reduxjs/toolkit';
import counterReducer from '../store/modules/counterSlice';
import {
  persistReducer,
  persistStore,
  FLUSH,
  REHYDRATE,
  PAUSE,
  PERSIST,
  PURGE,
  REGISTER,
} from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import authReducer from './modules/authSlice';

...

export const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: {
        ignoreActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
      },
    }),
});
...

store의 middleware에서 serializable 체크를 무시할 action들을 지정해줄 수 있다.

방법 2) 더 간단한 방법

stackoverflow 답변의 방법으로

export const store = configureStore({
  reducer: persistedReducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      serializableCheck: false
    }),
});

단순하게 serializableCheck를 false로만 지정해주어도 된다.

profile
개발로 밥벌이 하고 싶은 사람

0개의 댓글