programming language/react

[React] Next.js 알아보기 - 3탄 : next-redux-wrapper / 다이나믹 라우팅(Dynamic Routing) / swr 사용하기

공대키메라 2022. 7. 12. 22:30

지난 시간에 Next.js에서 SSG(Static Site Generation)와 SSR(Server Side Rendering)이 어떤 흐름으로 적용되는지 알아보았고, SSG, SSR을 어떻게 적용했는지 알아보았다. (궁금하면 여기 클릭!)

 

이번 시간에는 지난 시간에 이어서 SSR에서 어떻게 해야 action을 dispatch할 수 있는지 알아볼 것이다.

 

참고한 사이트는 다음과 같다.

 

출처:

https://www.youtube.com/watch?v=w8n7Soz7khw&ab_channel=LeighHalliday 

https://stackoverflow.com/questions/70426965/how-to-use-next-redux-wrapper-with-next-js-redux-toolkit-and-typescript-p

https://nextjs.org/docs/api-routes/introduction

https://swr.vercel.app/ko

 

1. 지난 시간에 이어서...

Next.js 알아보기 - 2탄에서는 SSR을 구현해 보았다.

 

물론 SSR로 데이터를 가져와서 이것을 깔끔하게 잘 보여주면 큰 문제는 없다. 

 

하지만, 필자가 하고싶은 것은 Login 여부에 따라서 화면에서 로그인이 되어 있으면 로그아웃 버튼을 Server side rendering으로 생성하는 것이다. 

 

만일 그렇지 않으면 외부 api에서 데이터를 가져올 때 처럼 Loading 창이 잠시 보였다가 데이터가 나오는 부자연스러운 현상이 생길 것이다. 

 

이것을 next-redux-wrapper로 해결해보겠다.

2. Next.js 실습 프로젝트 적용하기 - next-redux-wrapper

프로젝트는 지난 실습 프로젝트에서 크게 변한 것이 없다. 

 

 

다만 우리가 먼저 해줘야 하는 것들이 있다.

 

npm i next-redux-wrapper

src/store/store.js

import { combineReducers, configureStore } from "@reduxjs/toolkit";
import { userReducer } from "../reducers/user";
import createSagaMiddleware from "redux-saga";
import rootSaga from "../saga/index";
import logger from "../Logger/MyLogger";
import { HYDRATE, createWrapper } from "next-redux-wrapper";

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

export const createStore = () => {
  const saga = createSagaMiddleware();
  const store = configureStore({
    reducer,
    middleware: [logger, saga],
  });
  saga.run(rootSaga);
  return store;
};

export const wrapper = createWrapper(createStore);

 

기존의 store에 next-redux-wrapper의 HYDRATE를 적용하였다.

 

지난 번에는 combinereducers를 사용할 필요가 없다고 했는데...

 

이제보니 HYDRATE를 적용하기 위해서는 conbineReducers를 넣어주기 위해서 위와 같은 구조로 만들수밖에 없었다.

 

혹시 아는 사람 있으면 도와주면 감사하겠습니다 끼에엑!

 

이러한 목적 때문인지 아닌지는 모르겠지만 어찌됐든 reduxjs/toolkit에서도 combineReducers를 지원한다. 

pages/serverside.js

import axios from "axios";
import React, { useEffect } from "react";
import LoginForm from "../src/Login/LoginForm";
import Profile from "../src/Login/Profile";
import { useSelector } from "react-redux";
import { LOG_IN_SUCCESS } from "../src/reducers/user";
import { wrapper } from "../src/store/store";
import styles from "../styles/Home.module.css";

export default function serverSidePage({ todos }) {
  const { loginDone } = useSelector((state) => state.user);
  console.log(loginDone);
  return (
    <>
      <div className={styles.grid}>
        {loginDone ? <Profile /> : <LoginForm />}
        {todos?.length === 0 ? (
          <div>Loading...</div>
        ) : (
          todos?.map((todo) => (
            <div key={todo.id}>
              <p>
                {todo.id} : {todo.title}
              </p>
            </div>
          ))
        )}
      </div>
    </>
  );
}

export const getServerSideProps = wrapper.getServerSideProps(
  (store) => async (context) => {
    store.dispatch(LOG_IN_SUCCESS());
    const res = await fetch("https://jsonplaceholder.typicode.com/todos");
    const data = await res.json();

    return {
      props: { todos: data },
    };
  }
);

 

그러면 다음과 같은 화면을 볼 수 있다.

 

 

 실행 화면이 좀... 별로인것은 이해를 부탁드립니다 ㅎ...

 

우선 serverside 페이지로 이동을 한다. 

 

그러면 getServerSideProps 내부에서 store에 있는 action을 dispatch할 수 있다.

 

dispatch를 하게 되면 실행 결과를 src/store/store.js의 HYDRATE로 보내준다. 

3. Next.js -Dynamic API Routes (동적 API 라우트)

 

폴더에 다음과 같이 파일을 만들어주고 접속하면 대괄호 안에 숫자가 api 주소가 된다. 

pages/post/[id].js

import { useRouter } from "next/router";

const Post = () => {
  const router = useRouter();
  const { id } = router.query;
  return (
    <>
      <div style={{ margin: 20 }}>{id}</div>
    </>
  );
};

export default Post;

 

 

이게 전부다. 뭘 더 알아야 하나? 더 읽어보면 물론 좋지만 이게... 이게 전부라고 보인다. (건방지네 키메라 키에엑!)

3. swr사용하기

swr이란 데이터를 가져오기 위한 React Hooks다.

 

https://swr.vercel.app/ko

 

swr를 사용하면 데이터를 가져오는 로직을 단순화할 수 있으니 많이 사용한다고 한다. 

 

그러면 우선 다운을 받고 아주 간단하게 사용해보도록 하겠다.

 

npm i swr

pages/post/[id].js - swr 추가

import axios from "axios";
import { useRouter } from "next/router";
import useSWR from "swr";

const fetcher = (url) =>
  axios.get(url, { withCredentials: true }).then((result) => result.data);

const Post = () => {
  const { data: todoData, error } = useSWR(
    "https://jsonplaceholder.typicode.com/users",
    fetcher
  );
  console.log("todoData :: ", todoData);
  const router = useRouter();
  const { id } = router.query;
  return (
    <>
      <div style={{ margin: 20 }}>{id}</div>
    </>
  );
};

export default Post;

 

 

뭐... 그냥 api 데이터를 좀 더 편하게 받을 수 있게 사용하는 hook이다. 

 

솔직히 더 많은 내용이 적혀있지만 필요할 때 더 읽어보고 사용할 것이다. 

 


이번 글은 솔직히 날로 먹는거 같긴 하다.

 

다음에는 좀 더 흥미로운 예제로 글을 가득 채우도록 하겠다.