본문 바로가기

공부/Next

Next.js 알아보기 4 (주요 렌더링 기법)

반응형

 

CSR(Client Side Rendering) 📖

 

특징

  • 순수 리액트 사용했을 때 100%
  • 브라우저에서 js를 이용해 동적으로 페이지를 렌더링
  • 렌더링의 주체 : 클라이언트

장단점 ✅

  • (최초 로드 후) 사용자와의 상호작용이 빠르고 부드럽습니다.
  • 서버 부하가 적고, 서버에 추가적인 요청을 보낼 필요가 없기 때문에 사용자 경험이 좋습니다.

  • 첫 페이지 로딩 시간(Time To View)이 길 수 있습니다.
  • js가 로딩되고 실행될 때까지 페이지가 비어있어 SEO에 불리합니다.

 

직접 구현하기

 

아래 코드처럼 `"use client"`옵션을 추가하 사용할 수 있습니다.

"use client";

import Image from "next/image";
import React, { useEffect, useState } from "react";

import type { RandomUser } from "@/types";

const SSG = () => {
  const [user, setUser] = useState<RandomUser | null>(null);

  useEffect(() => {
    const fetchUser = async () => {
      const response = await fetch(`https://randomuser.me/api`);
      const { results } = await response.json();
      setUser(results[0]);
    };

    fetchUser();
  }, []);

  if (!user) {
    return <div>로딩중...</div>;
  }

  return (
    <></>
  );
};

export default SSG;

 

SSR(Server Side Rendering) 📖

 

특징  

  • 렌더링 주체 : 서버
  • 클라이언트 요청 시 렌더링

장단점 ✅

  • 빠른 로딩 속도(TTV)와 높은 보안성을 제공합니다.
  • SEO 최적화가 좋습니다.
  • 실시간 데이터를 사용하고 마이페이지처럼 데이터에 의존한 페이지 구성이 가능합니다.

  • 사이트 콘텐츠가 변경되면 전체 사이트를 다시 빌드해야 하기 때문에 시간이 오래 걸릴 수 있습니다. (서버 과부하)
  • 요청할 때마다 페이지를 만들어야 합니다.

 

직접 구현하기

아래처럼 컴포넌트 앞에 `async`키워드를 붙이게 되면 해당 컴포넌트 내부에서 패칭을 사용할 수 있습니다. 그리고 `cache: "no-store"`속성을 지정하게 되면 요청이 있을 때마다 지속해서 갱신해 줍니다.

// src>components>rendering>SSR.tsx

import type { RandomUser } from "@/types";

const SSR = async () => {
  const response = await fetch(`https://randomuser.me/api`, {
    cache: "no-store",
  });
  const { results } = await response.json();
  const user: RandomUser = results[0];

  return (
    <></>
  );
};

export default SSR;

 

 

SSG(Static Site Generation) 📖

 

특징  

  • 최초 빌드 시에만 생성됨
  • 서버에서 페이지를 렌더링해 클라이언트에 HTML을 전달하는 방식
  • 사전에 미리 정적페이지를 여러 개 만들어놓고 요청을 보내면 서버에서는 만들어져 있는 사이트를 제공

장단점 ✅

  • 첫 페이지 로딩 시간이 매우 짧고, 빠르게 페이지를 볼 수 있습니다.
  • SEO유리하고 CDN 캐싱이 가능합니다.

  • 정적인 데이터에만 사용할 수 있습니다.
  • CSR보다 상호작용이 느릴 수 있습니다. 또한 서버 부하가 클 수 있습니다.
  • 마이페이지처럼 데이터에 의존하여 화면을 그려주는 경우 사용이 불가합니다.

 

직접 구현하기

// SSG TEST : 아무것도 하지 않으면 SSG!

import ProductList from '@/components/ProductList';
import { Product } from '@/types';

const ProductsPage = async () => {
  const response = await fetch('http://localhost:4000/products');
  const products: Product[] = await response.json();

  return (
    <div>
      <h1>Products</h1>
      <ProductList products={products} />
    </div>
  );
};

export default ProductsPage;

 

아래 코드처럼 fetch에 아무것도 붙이지 않거나, `cache: "force-cache"`속성을 사용하게 되면 `SSG`를 사용할 수 있고 아무리 새로고침을 해도 동일한 페이지만 출력합니다.

const response = await fetch('http://localhost:4000/products');

const response = await fetch('http://localhost:4000/products',{
  cache: "force-cache"
});

 

 

ISR(Incremental Static Regeneration) 📖

 

특징  

  • SSG처럼 정적 페이지를 제공
  • 설정한 주기만큼 페이지를 계속 생성해 줌
  • 정적 페이지만 먼저 보여주고, 필요에 따라 서버에서 페이지를 재생성하는 방식

장단점 ✅

  • 정적 페이지를 먼저 제공하므로 사용자 경험이 좋습니다.
  • 콘텐츠가 변경되었을 때 서버에서 페이지를 재생성하므로 최신 상태를(그나마) 유지할 수 있습니다.

  • 동적인 콘텐츠를 다루기에 한계가 있을 수 있습니다.
  • 마이페이지처럼 데이터에 의존하여 화면을 그려주는 경우 사용이 불가합니다.

 

직접 구현하기

import Image from "next/image";
import React from "react";

import type { RandomUser } from "@/types";

const ISR = async () => {
  const response = await fetch(`https://randomuser.me/api`, {
    next: {
      revalidate: 5,
    },
  });
  const { results } = await response.json();
  const user: RandomUser = results[0];

  return (
    <></>
  );
};

export default ISR;

 

or

// src>app>rendering>page.tsx

import ISR from "@/components/rendering/ISR";
import React from "react";

export const revalidate = 5;

const RenderingTestPage = () => {
  return (
    <div>
      <h1>4가지 렌더링 방식을 테스트합니다.</h1>
      <ISR />
    </div>
  );
};

export default RenderingTestPage;

 

이처럼 fetch에 옵션으로 `revalidate: 5`를 설정해 주거나 page.tsx 컴포넌트에 `revalidate`를 export 해주는 방식으로 사용하게 되면 주어진 시간에 한 번씩 갱신해 줍니다.

const response = await fetch(`https://randomuser.me/api`, {
  next: {
    revalidate: 5,
  },
});

export const revalidate = 5;

 

종합 비교 📖

  CSR SSR SSG ISR
빌드 시간 짧다 짧다 길다 길다
SEO 나쁨 좋음 좋음 좋음
페이지 요청에 따른 응답 시간 보통 길다 짧다 짧다
최신 정보인가? 맞음 맞음 아님 아닐 수 있음

 

 

다음 게시물

 

Next.js 알아보기 5 (Suspense, Loading, Error, Streaming SSR)

Loading UI 📖✨ Next.js 14의 App router에서 비동기 컴포넌트가 로드되는 동안 사용자에게 로딩 상태를 표시하는 기능입니다. 왜 중요할까?`사용자 경험 개선`: 로딩 중인 상태를 명확히 표시해 사용

mingos-habitat.tistory.com

 

 

반응형