Next

CSR, SSR, ISR 알아보기

와이다이어리 2025. 6. 2. 17:45
반응형

CSR(Client-Side Rendering)이란?

CSR은 브라우저에서 JavaScript가 실행되면서 데이터를 패칭하고 화면을 그리는 방식입니다.
Next.js, React 등에서는 가장 기본적인 데이터 패칭 전략이죠.

// pages/client-example.tsx
import { useEffect, useState } from "react";

export default function ClientPage() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch("/api/hello")
      .then((res) => res.json())
      .then((data) => setData(data));
  }, []);

  if (!data) return <p>로딩 중...</p>;

  return (
    <div>
      <h1>CSR 예제</h1>
      <p>서버에서 받은 메시지: {data.message}</p>
    </div>
  );
}

특징

  • 모든 데이터 요청은 브라우저에서 직접 이뤄집니다.
  • 초기 HTML은 빈 껍데기 → JavaScript가 실행되면 내용이 보입니다.
  • React의 useEffect, useQuery 등과 함께 주로 사용됩니다.

SSR (Server-Side Rendering)이란?

 

SSR은 서버에서 HTML을 미리 생성해서 브라우저에 전달하는 방식입니다. 사용자가 웹페이지에 접근하면, 서버가 해당 페이지를 렌더링한 HTML을 응답으로 보내고, 브라우저는 그 HTML을 그대로 화면에 띄웁니다.

 

왜 SSR을 쓸까?

 

  • 초기 로딩 속도 향상
    → 브라우저가 JS 로딩 전에 먼저 완성된 HTML을 받아볼 수 있습니다.
  • SEO에 유리
    → 검색 엔진이 페이지에 접근할 때, HTML 안에 콘텐츠가 이미 있기 때문에 인덱싱이 잘 됩니다.
  • 최신 데이터를 보여줘야 할 때
    → 사용자가 페이지를 요청할 때마다 데이터를 가져오기 때문에 항상 최신 정보를 제공합니다.

Next.js에서 SSR 구현 방법

 

// pages/news.tsx
export async function getServerSideProps() {
  const res = await fetch("https://api.example.com/news");
  const data = await res.json();

  return {
    props: {
      news: data,
    },
  };
}

export default function NewsPage({ news }) {
  return (
    <div>
      <h1>실시간 뉴스</h1>
      <ul>
        {news.map((item) => (
          <li key={item.id}>{item.title}</li>
        ))}
      </ul>
    </div>
  );
}

 

 

 

  • 사용자가 /news 페이지에 접근할 때마다 서버가 https://api.example.com/news 에 요청을 보내 데이터를 가져옵니다.
  • 그리고 해당 데이터를 이용해 완성된 HTML을 브라우저에 전달합니다.

ISR (Incremental Static Regeneration)이란?

ISR은 SSG(정적 생성) 기반이지만, 특정 시간마다 페이지를 새로 갱신하는 전략입니다.
Next.js가 제공하는 기능으로, 정적 페이지의 성능서버 렌더링의 유연성을 동시에 가져갈 수 있어요.

 

// pages/blog/[id].tsx
export async function getStaticProps({ params }) {
  const res = await fetch(`https://api.example.com/posts/${params.id}`);
  const post = await res.json();

  return {
    props: {
      post,
    },
    revalidate: 60, // 60초마다 페이지 갱신
  };
}

export async function getStaticPaths() {
  const res = await fetch("https://api.example.com/posts");
  const posts = await res.json();

  const paths = posts.map((post) => ({
    params: { id: post.id.toString() },
  }));

  return {
    paths,
    fallback: "blocking", // 없는 페이지도 생성해줌
  };
}

export default function BlogPost({ post }) {
  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </article>
  );
}

 

 

 

반응형