(21.07.30) redux-persist 사용하기

도깨비젤리

·

2021. 7. 30. 17:53

작은 지식이라도, 하루에 하나씩.


 

한 줄 요약


🦄redux-persist는 redux의 state를 로컬/세션 스토리지에 저장하도록 하는 라이브러리🦄

🦄persist를 사용하기 위해서는 store를 persistedReducer로 만든 리듀서로 만들고, persistStore라는 함수로 store를 감싼 후, store를 **export** 해줘야한다.🦄

 

 

persist를 이용하기 위한 store 셋팅


// store를 모아서 통합하는 index.ts


import { combineReducers, createStore } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import { persistReducer, persistStore } from "redux-persist";
import storage from "redux-persist/lib/storage";

import clientLogin from "./clientLogin";


const persistConfig = {
  key: "root",
  storage,
  whitelist: ["clientLogin"], // required인지 모르겠당..
};

export const rootReducer = combineReducers({ clientLogin: clientLogin });


const persistedReducer = persistReducer(persistConfig, rootReducer);

export default function configureStore() {
  const store = createStore(persistedReducer, composeWithDevTools());
  const persistor = persistStore(store);
  return { store, persistor };
}

 

여기서 whitelist는 로컬 스토리지에 저장할 리듀서를 지정하는 곳이다. 저길 생략하면 모든 리듀서가 로컬스토리지에 저장된다.

 

이 config와 persistedReucer를 사용해 redux-persist화 된 리듀서를 만들어줍니다.

 

이후, createStore를 이용해, persistedReducer로 스토어를 만들어주고, persistor라는 것을 persistStore를 통해 만들어줍니다

 

나중에 나오겠지만, persistor는 스토리지와 redux를 동기화 시키는 역할을 한다고 합니다. (<-- 긁어모은 지식이라 확실하지는 않습니다.)

 

//index.tsx (루트 컴포넌트)

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import TestCompo from "@components/TestCompo";
import configureStore from "./modules/index";


const { store, persistor } = configureStore();

const Root = () => (
  <Provider store={store}>
    <PersistGate loading={<TestCompo />} persistor={persistor}>
      <App />
    </PersistGate>
  </Provider>
);

 

이후 루트 컴포넌트로 이동하여, 루트를 provider 안에 PersistGate라는 컴포넌트로 감싸줍니다.

 

여기서 loading props는 리덕스와 스토리지가 동기화 될 동안 표시될 컴포넌트를 지정하는 것이고, persistor 자리에는 

위에서 제작한 perisist화 된 스토어와 persitor를 불러와서 사용해야합니다.

 

 

원래 저는 이 index.tsx 에서 스토어와 reducer를 perisist화 하였는데, 그렇게 하니 화면에 계속 loading 컴포넌트만 랜더링 되고, <App/>이 랜더링 되지 않는 일이 발생했습니다.

 

근데, 외부에서 스토어와 reducer를 perisist화 한 다음 import 하니, 아무런 문제 없이 잘 되는 겁니다. 

 

왜 이런 기묘한 문제가 일어났는지 여러방면으로 수소문 할 결과,  리액트가 스토어를 인식하지 못해서라고 하는것 같다고 합니다.

 

redux-persist를 사용해본 코치님들의 코드를 보면서 같이 고민해봤는데, 코치님은 처음의 저 처럼 루트 컴포넌트 자체에서 perisist 화 하여도 에러가 나질 않았습니다.

 

저와 다른 점은 단 하나, createStore로 만든 store를 export 해줬다는 것입니다.

 

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import TestCompo from "@components/TestCompo";
import { composeWithDevTools } from "redux-devtools-extension";
import rootReducer from "./modules/index";
import { createStore } from "redux";
import { persistStore } from "redux-persist";

const store = createStore(rootReducer, composeWithDevTools());
const persistor = persistStore(store);
// //여기서도 export를 해줬어야한다.

export store

const Root = () => (
  <Provider store={store}>
    <PersistGate loading={<TestCompo />} persistor={persistor}>
      <App />
    </PersistGate>
  </Provider>
);

ReactDOM.render(<Root />, document.getElementById("root"));

대충 이런 느낌이였는데, 이렇게 스토어를 export 해주니 잘 돌아갔다는 말씀을 하셨습니다.

 

게다가, 확신하지는 못하지만, 아마도 export를 해주지 않아 PersistGate가 스토어를 읽어들이지 못해서 loading 컴포넌트만 계속 랜더링 하고 있는게 아닌라는 추론을 해주셨습니다.

 

듣고보니 상당히 일리있는 것 같습니다.

 

여하튼, 좀 더 실험을 해봐야겠지만, redux-persist를 사용할 때는 스토어가 export 되었는지를 꼭 확인해야겠고, 가급적이면 루트 컴포넌트 파일 외부에서, 스토어를 완성하여 가져오는 편이 정신건강에 좋을 것 같습니다.