I turn coffee into code ☕ → 💻 자세히보기

개발/Next.js

Next.js의 렌더링 방식 (CSR/SSR/SSG/ISR)

xuwon 2025. 8. 7. 22:24

Next.js의 렌더링 방식에 대해 알아보자.

개념

CSR - 사용자 브라우저가 페이지를 받아온 뒤, API를 호출해 데이터를 가져와 렌더링
SSR - 사용자가 요청할 때마다 서버가 API에서 데이터를 받아 HTML을 만들어 전달
SSG - 빌드 시점에 API에서 데이터를 받아 미리 HTML을 만들어 둠 → 빠른 응답, 하지만 고정 데이터
ISR - SSG에 '재생성 주기'를 두어, 주기마다 서버가 새로 HTML을 만들어 업데이트


CSR (Client-Side Rendering)

브라우저가 HTML + JS를 받고, 클라이언트에서 API를 호출해 데이터 받아와서 렌더링
ex) SPA, React 앱 다수

장점
- 빠른 초기 인터랙션
- 동적 UI, 실시간 업데이트 용이

단점
- SEO에 불리
- 초기 빈 화면 → UX 저하

API 호출 시점
- 클라이언트 렌더링 후 호출

언제 사용?
- 로그인 폼, 글쓰기, 대화형 UI 등
- 개인화가 심한 페이지 (실시간 채팅, 이메일... 등) → 사용자 행동 기반 동적 변화!
- SEO가 중요하지 않은 페이지

"use client"
import { useEffect, useState } from "react"

export default function UserProfile() {
  const [user, setUser] = useState(null)

  useEffect(() => {
    fetch("/api/user")
      .then(res => res.json())
      .then(data => setUser(data))
  }, [])

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

  return <div>안녕하세요, {user.name}님!</div>
}

SSR (Server-Side Rendering)

페이지 요청 시 서버가 API를 호출해 데이터를 받아서 HTML을 즉시 생성 후 전송
사용자별 맞춤 페이지 가능!

장점
- SEO 최적화
- 사용자 맞춤 데이터 제공 가능

단점
- 서버 부하 증가
- 요청마다 데이터 호출 → 느릴 수 있음

API 호출 시점
- 사용자가 페이지 요청 시 서버에서 호출

언제 사용?
- 로그인 후 대시보드, 마이페이지
- SEO가 필요한 동적 데이터 페이지

export async function getServerSideProps(context) {
  const res = await fetch("https://api.example.com/user", {
    headers: { cookie: context.req.headers.cookie || "" }
  })
  const user = await res.json()

  return {
    props: { user },
  }
}

export default function Dashboard({ user }) {
  return <h1>{user.name}님, 환영합니다!</h1>
}

SSG (Static Site Generation)

빌드 시 API에서 데이터를 받아 미리 HTML 생성
정적인 콘텐츠에 최적화!

장점
- 매우 빠른 초기 로딩 속도
- CDN 캐싱 활용 가능

단점
- 빌드 후 데이터 변경 불가
- 최신성 반영 어려움

API 호출 시점
- 빌드 시 호출

언제 사용?
- 블로그, 공지사항, 마케팅 페이지 등 (작성 후 변경될 가능성 적음)
- 자주 변하지 않는 콘텐츠

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

  return {
    props: { posts },
  }
}

export default function Blog({ posts }) {
  return (
    <ul>
      {posts.map(post => <li key={post.id}>{post.title}</li>)}
    </ul>
  )
}

ISR (Incremental Static Regeneration)

SSG + 재생성 기능
빌드 시 생성하고, 주기마다 재생성하여 데이터 최신성 유지

장점
- SSG 장점 + 최신 데이터 반영 가능
- 빠른 초기 응답 + 주기적 업데이트

단점
- 즉각적인 최신 데이터 반영은 불가 (재생성 주기 내 한계)

API 호출 시점
- 빌드 시 + 재생성 시 호출

언제 사용?
- 뉴스, 상품 목록, 변동 많은 콘텐츠 
- 빠른 응답 + 최신성 둘 다 필요한 경우

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

  return {
    props: { products },
    revalidate: 60, // 60초마다 재생성
  }
}

export default function Products({ products }) {
  return (
    <ul>
      {products.map(product => <li key={product.id}>{product.name}</li>)}
    </ul>
  )
}

활용

 

  • SEO가 중요하고, 자주 변하지 않는 콘텐츠 → SSG
  • SEO + 사용자별 데이터 필요 → SSR
  • 자주 변하는 콘텐츠지만 CDN 캐싱도 활용하고 싶다면 → ISR
  • 빠른 반응과 사용자 상호작용, SEO가 덜 중요하면 → CSR

CDN (Content Delivery Network)

전 세계에서 여러 위치에 있는 서버(엣지 서버)에 콘텐츠를 미리 복사해 두고, 사용자에게 가장 가까운 서버에서 전달하는 방식

CDN이 가능한 조건

→ 정적 파일일수록 CDN에 올리기 쉬움! (SSG > ISR > SSR)

CDN 배포는 어떻게 사용?

Next.js에서 SSG나 ISR로 만든 페이지는 정적 HTML로 생성되므로

- Vercel, Netlify, Cloudflare Pages 같은 플랫폼이
- 이 HTML/CSS/JS 파일을 CDN에 자동으로 배포해줌!
- 그 결과 어느 나라에서든 빠른 로딩 가능