본문 바로가기

코딩/Next.js

Next.js Router 만들기 과제

반응형

각각 App Router를 직접 구현해보기

SSR 서버에서 데이터 fetch 해서 렌더링하기

SSG 빌드 시 데이터를 fetch 하여 정적 페이지 만들기

CSR 클라이언트 측에서 데이터 fetch 해서 렌더링하기

ISR 정적으로 생성된 페이지를 일정 시간마다 재생성하도록 설정하기

 

  1. src 안에 app 폴더만들고 각각 하위폴더 만들기 (SSR,SSG,CSR,ISR)
  2. 메인 rootpage 를 만들고 각각 nav 를 만들어서 Link 로 연결하기
  • RootPage (메인)
    - 주의사항 : Link 를 react-router-dom 이 아닌 next/link 로 import 해야 함.
import Link from "next/link";
import React from "react";

const RootPage = () => {
  return (
    <ul>
      <li>
        <Link href={"/ssr"}>SSR</Link>
      </li>
      <li>
        <Link href={"/ssg"}>SSG</Link>
      </li>
      <li>
        <Link href={"/csr"}>CSR</Link>
      </li>
      <li>
        <Link href={"/isr"}>ISR</Link>
      </li>
    </ul>
  );
};
export default RootPage;
  • SSR Page (서버에서 데이터를 fetch 하여 렌더링하기)
    - no-store 로 최신 데이터를 매번 가져와야 할 때 유용하지만 각 요청마다 서버에서 동적으로 페이지를 생성해서 응답 시간이 길어질 수 있다.
    - 뉴스피드나 주식 등에 적합하다.
const SSRPage = async () => {
  const res = await fetch("http://localhost:5000/posts", {
    cache: "no-store",
  });

  const data = await res.json();

  return (
    <div>
      SSR Page
      <div>{JSON.stringify(data)}</div>
    </div>
  );
};
export default SSRPage;
  • SSG (데이터를 fetch하여 정적 페이지를 생성)
    - 엄청 빠른 응답 시간을 제공하고, 페이지가 미리 생성되어 있기 때문에 서버 요청 없이 빠르게 사용자에게 전달된다.

    - 변경이 적은 블로그나 문서 등에 적합하다.
import React from "react";
import { Post } from "../../../types/route.type";

const SSGPage = async () => {
  const res = await fetch("http://localhost:5000/posts");
  const posts: Post[] = await res.json();

  return (
    <div>
      <h1>SSG Page</h1>
      {posts.map(({ id, title, author }) => (
        <div key={id}>
          <li>{id}</li>
          <li>{title}</li>
          <li>{author}</li>
        </div>
      ))}
    </div>
  );
};

export default SSGPage;
  • CSR (클라이언트 측에서 데이터를 fetch하여 페이지에 렌더링)
    - use Client 를 사용하여 서버 컴포넌트와 구별하고, 클라이언트에서만 사용할 수 있는 훅들을 사용하기 위해 필요하다.
    - useState 는 데이터를 저장하고 관리하는 데 사용
    - useEffect 는 컴포넌트가 마운트될 때 특정 작업(여기서는 데이터 가져오기)을 실행하는 훅
    - CSR에서는 클라이언트 측에서 페이지가 로드된 후 데이터를 가져와야 하기 때문에 useEffect를 사용하여 비동기 데이터 요청한다.
"use client";

import React, { useEffect, useState } from "react";
import { Post } from "../../../types/route.type";

const CSRPage = () => {
  const [posts, setPosts] = useState<Post[]>([]); // posts 상태 정의
  const [loading, setLoading] = useState(true); // 데이터 로딩 상태 정의

  useEffect(() => {
    const fecthPosts = async () => {
      try {
        const res = await fetch("http://localhost:5000/posts");
        const data: Post[] = await res.json();
        setPosts(data); // 상태 업데이트
      } catch (error) {
        console.error("Error fetching posts:", error);
      } finally {
        setLoading(false); // 로딩 상태 업데이트
      }
    };
    fecthPosts();
  }, []);

  if (loading) return <div>Loading...</div>;

  return (
    <div>
      <h1>CSR Page</h1>
      {posts.map(({ id, title, author }) => (
        <div key={id}>
          <li>{id}</li>
          <li>{title}</li>
          <li>{author}</li>
        </div>
      ))}
    </div>
  );
};

export default CSRPage;
  • ISR (정적으로 생성된 페이지를 일정 시간마다 재생성하도록 설정)
    - revalidate 를 사용하여 10초마다 페이지를 재생성하지만, 새로고침이 되진 않는다.
import React from "react";
import { Post } from "../../../types/route.type";

export const revalidate = 10;

const ISRPage = async () => {
  const res = await fetch("http://localhost:5000/posts");
  const posts: Post[] = await res.json();
  return (
    <div>
      <h1>ISR Page</h1>
      {posts.map(({ id, title, author }) => (
        <div key={id}>
          <li>{id}</li>
          <li>{title}</li>
          <li>{author}</li>
        </div>
      ))}
    </div>
  );
};

export default ISRPage;

 

쉽기도 하고 어렵기도 한데 next.js 는 좀 좋은 듯

반응형