본문으로 건너뛰기
yutils

SSR · SSG · SPA · RSC 는 어떻게 다를까?

HTML 이 어디서 만들어지나 (server / build / client), TTFB vs LCP vs interactivity trade-off, 각 모델이 보내는 bundle 크기, 언제 무엇을 선택, 'Next.js App Router' 가 순수 RSC 아니고 hybrid 인 이유.

약 10분 읽기

"SPA / SSR / SSG / RSC / ISR / PPR" — Next.js docs 의 단어 폭격. 모두 "page 가 어디서 만들어지나" + "JS 가 얼마나 client 로 가나" 의 다른 조합. 이 가이드는 각 모델의 정확한 차이, TTFB / LCP / interactivity trade-off, "Next.js App Router 가 순수 RSC 아닌" 진실을 정리한다.

4 가지 (+ 2) 의 구분 기준

기준 1 — HTML 이 어디서 만들어지나:
  - Build time → SSG
  - Server (request 시) → SSR
  - Client (browser) → SPA
  - Server, 단 component 단위 → RSC

기준 2 — JS bundle 에 무엇이 포함:
  - 모든 component code → SPA, SSR
  - client-only component 만 → RSC

기준 3 — 언제 user interactive:
  - download + hydration 끝나야 → SSR, SSG
  - download 끝나야 → SPA
  - hydration 거의 0 → Qwik, Astro island

기준 4 — 데이터 fetch 가 어디서:
  - client 에서 (useEffect / TanStack Query) → SPA
  - server 에서 (page 호출 전) → SSR, RSC
  - build time → SSG

SPA (Single Page Application)

흐름:
  1. server → index.html (거의 빈) + bundle.js
  2. browser → bundle.js download (~수 MB)
  3. JS 실행 → React/Vue/Svelte 가 DOM build
  4. useEffect → API fetch
  5. data 도착 → render
  6. user interactive

TTFB: 빠름 (small HTML)
LCP: 느림 (JS download + execute + fetch 후에야 content)
Interactive: 느림
SEO: 안 좋음 (crawler 가 JS 실행 못 하면 빈 HTML)

대표: CRA, Vite default, React Router

좋음: 사내 dashboard, authenticated app (SEO 무관)
나쁨: 마케팅 사이트, 블로그, e-commerce

SSR (Server-Side Rendering)

흐름:
  1. user 요청 → server 가 React render → HTML 만듦 (DB fetch 포함)
  2. browser → HTML 즉시 paint
  3. JS bundle download
  4. hydration → interactive

TTFB: 중간 (server render 시간 포함)
LCP: 빠름 (HTML 즉시 paint)
Interactive: 중간 (hydration cost)
SEO: 좋음 (HTML 완성된 상태)

대표: Next.js Pages Router, Remix, Nuxt 3

좋음: 매 요청마다 fresh data (대시보드, news feed)
나쁨: TTFB 가 중요한 글로벌 사이트 (CDN edge X 면 매번 server)

SSG (Static Site Generation)

흐름:
  Build time: 모든 page 미리 render → HTML 파일들 (CDN 에 deploy)
  Runtime: CDN 에서 즉시 static HTML 반환

TTFB: 매우 빠름 (CDN edge)
LCP: 매우 빠름
Interactive: 중간 (hydration)
SEO: 매우 좋음
Cost: 거의 0 (server 안 도는 시간 동안 idle)

대표: Next.js generateStaticParams, Astro, Hugo, Gatsby

좋음: 블로그, docs, 마케팅 사이트 (변경 빈도 낮음)
나쁨: 자주 변경되는 content (rebuild 필요)
      개인화 content (user 별 다른 HTML 불가능)

ISR (Incremental Static Regeneration, Next.js)

SSG 의 한계 (rebuild 시간 + 변경 빈도) 해소:
  - 처음엔 SSG (정적 HTML)
  - 일정 시간 후 (revalidate=60) stale 표시
  - 다음 요청 시 → stale 즉시 반환 + 백그라운드 regenerate
  - 다음다음 요청 시 → 새 HTML

→ "최대 60 초 stale OK" 의 trade-off 로 SSG 의 속도 + SSR 의 freshness.
→ Wikipedia / news 사이트의 best fit.

RSC (React Server Components)

흐름:
  1. user 요청 → server 가 React tree → RSC payload (text format)
  2. server 가 streaming response 시작 (HTML 도 함께)
  3. browser HTML 받자마자 paint (TTFB 빠름)
  4. JS bundle download — server component 의 코드 X (작음)
  5. hydration (client component 만)

TTFB: 빠름 (streaming)
LCP: 빠름
Interactive: 빠름 (작은 JS)
SEO: 매우 좋음 (HTML completion)
Bundle: 작음 (server-only 코드 제외)

대표: Next.js App Router, Remix v2+

핵심 신규성: bundle size 감소 + server logic 을 component 안에 직접

PPR (Partial Prerendering, Next.js 14+)

page 의 일부만 static + 나머지 dynamic 으로 mix:

  page:
    <Header />            ← static (build 타임)
    <UserGreeting />      ← dynamic (request 시, user 별)
    <Footer />            ← static

  Build: static 부분만 HTML 미리 → CDN 캐시
  Runtime: request 오면 static HTML 즉시 stream + dynamic 부분만 server render → stream

→ TTFB 거의 0 (static 즉시 시작) + dynamic 부분도 streaming.
→ SSR 의 personalization + SSG 의 속도 통합.

상태: 2026-05 기준 Next.js 의 experimental → stable 진행 중.

Trade-off 표

모델TTFBLCPTTIBundleSEOCost
SPA빠름느림느림나쁨저렴 (CDN 만)
SSR중간빠름중간좋음비쌈 (server 매번)
SSG매우 빠름매우 빠름중간매우 좋음저렴
ISR매우 빠름매우 빠름중간매우 좋음저렴 + regenerate cost
RSC빠름빠름빠름작음 ✓매우 좋음중간 (server logic)
PPR매우 빠름매우 빠름빠름작음매우 좋음중간

Next.js App Router 는 순수 RSC 아니다

Next.js App Router 의 default 가 RSC 라고 하지만 — 실제로는:
  - server component (RSC) — code 가 client 안 감
  - client component ("use client") — SPA 같은 hydration
  - SSR — client component 의 first render 도 server 에서
  - SSG — static 으로 결정된 path 는 build time
  - ISR — revalidate 박은 page
  - PPR — partial prerendering (experimental)

→ Next.js App Router = RSC + SSR + SSG + ISR + PPR 의 hybrid.
   각 page / component 의 mode 가 다르게 박힘.

이 hybrid 가 modern 답:
  - 가능하면 server component (bundle ↓)
  - 동적 부분만 client
  - 자주 변경 X 면 SSG, 자주 변경이면 ISR, request 마다 다르면 SSR
  - PPR 로 static + dynamic streaming mix

흔한 함정

  • "우리는 SSR 이다" 단순화 — 실제는 mixed. 각 route / component 의 mode 명시.
  • 모든 page 를 SSG — 자주 변경되는 데이터면 rebuild 부담. ISR 또는 SSR.
  • SPA 의 SEO 무시 — 마케팅 / blog 가 SPA 면 검색 노출 어려움. SSR 또는 SSG 로.
  • 모든 page 를 SSR — server cost ↑ + edge cache 못 활용. SSG / ISR 검토.
  • RSC 의 "use client" leaf 위치 — page top 에 박으면 RSC 효과 0. component tree 의 leaf 가까이.

마무리

SPA / SSR / SSG / RSC 의 차이 = "HTML 어디서" + "JS 얼마나 client". modern Next.js App Router 는 6 mode 의 hybrid — page / component 마다 다르게.

실용 선택: - 블로그 / docs / 마케팅 = SSG (or ISR) - 자주 변경되는 dashboard = SSR (또는 RSC) - 글로벌 personalized = PPR + edge - 인증된 internal app (SEO 무관) = SPA

가이드 목록으로