Next.js에서 redux-toolkit 세팅하기

이정민 Lee Jeong Min·2021년 6월 15일
10

Web

목록 보기
2/4
post-thumbnail

CSR에서 세팅하는 거랑 뭐가 다른데?

Next.js는 처음 렌더링시 SSR을 하게 됩니다. 따라서 store를 호출할 때마다 redux store을 새로 생성하게 되는데요, 이 때 생성하는 redux store와 이후 CSR시 생성하는 redux store가 다르기 때문에 이 둘을 합쳐주는 로직이 필요합니다.

우선 next-redux-wrapper가 필요한데요,
이 라이브러리가 없다면 Next.jsgetInitialProps, getServerSideProps, getStaticProps 내에서 redux store에 접근을 할 수 없습니다.

store/index.ts

import {
  AnyAction,
  combineReducers,
  configureStore,
  getDefaultMiddleware,
} from "@reduxjs/toolkit";
import { HYDRATE, createWrapper } from "next-redux-wrapper";
import axios from "axios";
import getConfig from "next/config";

axios.defaults.baseURL = getConfig().publicRuntimeConfig.apiServerUrl;

export const reducer = (state, action) => {
  if (action.type === HYDRATE) {
    return {
      ...state,
      ...action.payload,
    };
  }
  return combineReducers({
    /* */
  })(state, action);
};

const makeStore = () =>
  configureStore({
    reducer,
    middleware: [
      ...getDefaultMiddleware({ thunk: true, serializableCheck: false }),
    ],
  });

export const wrapper = createWrapper(makeStore, {
  debug: process.env.NODE_ENV !== "production",
});

유저가 페이지를 요청할 때마다 새로운 redux store를 생성해야 하기 때문에 makeStore 함수를 작성해줍니다.

_app.tsx

import Head from "next/head";
import { wrapper } from "store";
import "index.css";

function MyApp({ Component, pageProps }) {
  return (
    <>
      <Head>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>BOOKBOOK</title>
      </Head>
      <Component {...pageProps} />
    </>
  );
}

export default wrapper.withRedux(MyApp);

그리고 나서 _app 파일에서 wrapperwithRedux HOC로 컴포넌트를 감싸주면 됩니다. 그럼 이제 각 페이지의 getInitialProps, getServerSideProps, getStaticProps 내에서 redux store에 접근할 수 있게 됩니다.

위의 store/index.ts를 보시면 reducer 함수를 정의해놓은 것을 볼 수 있는데요,
서버에서 생성한 redux store와 client에서 생성한 redux store가 다르기 때문에, 이렇게 서버에서 생성한 store의 상태를 HYDRATE라는 액션을 통해 client에 합쳐주는 작업이 필요합니다.

export const reducer = (state, action) => {
  if (action.type === HYDRATE) {
    return {
      ...state,
      ...action.payload,
    };
  }
  return combineReducers({
    /* */
  })(state, action);
};

action.payload에는 서버에서 생성한 store의 상태가 담겨있어 이 둘을 합쳐 새로운 client의 redux store의 상태를 만들게 됩니다.

profile
https://jeong-min.com/ <- 블로그 이전했습니다 :)

0개의 댓글