Web/React

React Redux - 새로고침 시에도 리덕스 내의 데이터를 유지하려면 어떤 방법을 써야할까요?

또롱또 2022. 5. 31. 03:08
728x90

https://11001.tistory.com/191

 

요약

  • redux-persist 패키지 사용
  • 자동로그인을 원하면 localStorage를 사용 
  • 브라우저를 닫으면 로그인이 풀리는 것을 원하면 sessionStorage를 사용

사용 목적

  • 리덕스는 웹 브라우저 창을 닫으면 모든 state가 리셋된다.
  • 유저 로그인 정보 같은 경우 브라우저를 닫아도 유지되어야 한다. 이런 경우 사용될 수 있음

원리

  1. App 이 불러와졌을 때 로컬스토리지에 있던 유저 정보 사용
  2. 서버에 현재 로그인 상태 재검증
  3. 서버가 응답한 로그인 정보로 업데이트
  4. 만약에 토큰이 만료되었을 시에는, 재로그인 요청

웹 스토리지 객체(web storage object) 개념 이해

  • 종류
    • localStorage
    • sessionStorage
  • localStorage와 sessionStorage브라우저 내에 키-값 쌍을 저장
  • 서버로 전송되지 않습니다. 그래서 쿠키보다 많은 데이터 저장 가능.
  • 도메인·프로토콜·포트로 정의되는 오리진(origin)에 묶여있어서 프로토콜과 서브 도메인이 다르면 데이터에 접근불가

메서드, 프로퍼티

  • 두 스토리지 객체는 동일한 메서드와 프로퍼티를 제공합니다.
  • setItem(key, value) – 키-값 쌍을 보관합니다.
  • getItem(key) – 키에 해당하는 값을 받아옵니다.
  • removeItem(key) – 키와 해당 값을 삭제합니다.
  • clear() – 모든 것을 삭제합니다.
  • key(index) – 인덱스(index)에 해당하는 키를 받아옵니다.
  • length – 저장된 항목의 개수를 얻습니다.

localStorage

  • 오리진(domain/port/protocol)이 같은 경우 데이터는 모든 탭과 창에서 공유됩니다.
  • 오리진만 같다면 url 경로는 달라도 동일한 결과를 볼 수 있습니다.
  • 브라우저나 OS가 재시작하더라도 데이터가 파기되지 않습니다.

sessionStorage

  • 현재 떠 있는 탭 내에서만 유지됩니다.
  • 같은 페이지여도 탭이 다르면 다른 곳에 저장됩니다.
  • 하나의 탭에 여러 iframe이 떠 있는 경우 동일 오리진에서 왔다고 취급하여 sessionStorage 공유됨
  • 새로 고침할 때 sessionStorage에 저장된 데이터는 사라지지 않습니다. 하지만 탭을 닫고 새로 열 때는 사라집니다.

redux-persist

  • localStorage 또는 sessionStorage에 저장하고자 하는 reducer state를 저장하여 새로고침 하여도 저장공간에 있는 데이터를 redux에 불러오는 방식
  • 자동로그인을 원하면 localStorage를 사용
  • 브라우저를 닫으면 로그인이 풀리는 것을 원하면 sessionStorage를 사용

Install

npm i redux-persist

localStorage

import storage from 'redux-persist/lib/storage

sessionStorage

import storageSession from 'redux-persist/lib/storage/session

combineReducers로 리듀서 묶어주기

// redux/rootReducer.js
import sellerInfo from "./modules/sellerInfo";
import board from "./modules/board";
import review from "./modules/review";
import { combineReducers } from "@reduxjs/toolkit";

export const rootReducer = combineReducers({
  board,
  review,
});

persist store 정의 - export하면 안된다!!!!

// redux/configureStore.js

import logger from "redux-logger";
import { configureStore } from "@reduxjs/toolkit";
import storageSession from "redux-persist/lib/storage/session";

import { persistStore, persistReducer } from "redux-persist";
import { rootReducer } from "./rootReducer";

const persistConfig = {
  key: "root", // localStorage에 저장합니다.
  storage: storageSession, // sessionStorage에 저장
  whitelist: ["user"], // 적용 대상목록 - reducer를 넣는게 아니라 reducer이름을 문자열로 넣어야한다!
  // blacklist: [""], // 제외 대상목록
};
// store는 Provider에 전달하여 리덕스 스토어를 사용하기 위함이고
// persistor는 PersistGate에 전달하여 로컬/세션 스토리지를 사용하기 위함

경고 ! 아래와 같이 사용하면 저장되지 않은 변수를 export 한 것이라서 Error 발생!!!

// did not work

export default () => {
const store = createStore(pReducer, middleware);
const persistor = persistStore(store);
return { store, persistor };
};

// did not work

export const store = createStore(pReducer, middleware);
export const persistor = persistStore(store);

persist store 사용

// src/index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./Components/App";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { getStore } from "redux/store";
import { ThemeProvider } from "styled-components";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import theme from "styles/theme";

// 아래처럼 함수 실행 결과를 받아서 사용해야 함. store, persistor 를 다이렉트로 못 가져옴
const { persistor, store } = getStore();

ReactDOM.render(
  <Provider store={store}>
    <PersistGate loading={null} persistor={persistor}> // 이 구문이 추가됨
      <React.StrictMode>
        <ThemeProvider theme={theme}>
          <App />
          <ToastContainer />
        </ThemeProvider>
      </React.StrictMode>
    </PersistGate>
  </Provider>,
  document.getElementById("root")
);
728x90