"매 페이지 마다 매 적절한 rendering 시점 의 선택 — 매 CSR / SSR / SSG / ISR / RSC 의 spectrum". 매 2010s SPA 의 CSR-only era 의 종료, 매 2020s Next.js 13+ App Router 의 RSC (React Server Components) 의 매 default 화. 매 2026 매 mix-and-match — 매 한 page 안 의 static shell + streaming SSR + island hydration 의 공존.
매 핵심
매 Strategy Spectrum
전략
매 HTML 생성 시점
매 JS hydration
매 use case
CSR
매 client runtime
매 모든 것
dashboard, internal tool
SSR
매 request time (server)
매 full
dynamic personalized
SSG
매 build time
매 full / partial
blog, docs, marketing
ISR
매 build + on-demand revalidate
매 full / partial
e-commerce catalog
RSC
매 server (no client JS for component)
매 client component 만
매 modern Next.js default
Streaming SSR
매 server, 매 chunk-by-chunk
매 progressive
매 large interactive page
매 Trade-off
CSR — 매 TTI (Time-to-Interactive) 의 빠름 (after JS load), 매 FCP 의 느림, 매 SEO 의 약함.
SSR — 매 FCP 의 빠름, 매 TTFB 의 느림 (server compute), 매 cache 의 어려움.
SSG — 매 가장 빠른 TTFB, 매 CDN 의 무한 scale, 매 stale 의 risk.
ISR — SSG 의 stale 의 해결, 매 first request 의 stale 의 가능.
RSC — 매 client bundle 의 축소, 매 framework lock-in.
매 RSC (React Server Components) 의 의미
매 component tree 의 server / client 의 split.
Server component — 매 DB 의 직접 fetch, 매 secret 의 access, 매 client JS 의 X.
Client component — 'use client' 의 마킹, 매 useState/useEffect 의 사용.
매 server payload 의 binary serialization (RSC wire format).
💻 패턴
Pattern 1: Next.js 15 Server Component (default)
// app/posts/page.tsx — 매 server 의 실행, 매 client JS 의 X
import{db}from'@/lib/db';exportdefaultasyncfunctionPostsPage() {constposts=awaitdb.posts.findMany({orderBy:{createdAt:'desc'}});return(<ul>{posts.map(p=><likey={p.id}>{p.title}</li>)}</ul>);}
// app/products/[id]/page.tsx
exportconstrevalidate=3600;// 매 1시간 마다 background revalidate
exportdefaultasyncfunctionProductPage({params}){constproduct=awaitfetchProduct(params.id);return<ProductDetailproduct={product}/>;}// 매 on-demand revalidation
import{revalidatePath}from'next/cache';exportasyncfunctionPOST(req: Request){const{path}=awaitreq.json();revalidatePath(path);returnResponse.json({revalidated: true});}
Pattern 5: Streaming SSR with Suspense
import{Suspense}from'react';exportdefaultfunctionDashboard() {return(<><Header/>{/* 매 즉시 stream */}<Suspensefallback={<Skeleton/>}><SlowAnalytics/>{/* 매 chunk 의 도착 시 stream */}</Suspense><Suspensefallback={<Skeleton/>}><SlowFeed/></Suspense></>);}
Pattern 6: Astro 5 Islands
---
// 매 build-time 의 server, 매 client JS 의 zero by default
import Counter from './Counter.tsx';
const posts = await Astro.glob('./posts/*.md');
---
<html>
<body>
<h1>Blog</h1>
{posts.map(p => <article>{p.frontmatter.title}</article>)}
<Counter client:visible /> {/* 매 viewport 의 진입 시 hydrate */}
</body>
</html>
언제: 매 page 의 적절한 rendering strategy 의 권고, RSC server/client boundary 의 review, revalidate 의 적절한 시간 의 제안.
언제 X: 매 specific framework migration 의 detailed plan — 매 codebase 의 scan 의 X.
❌ 안티패턴
모든 페이지 의 SSR: 매 cold-start latency, 매 cost 의 polynomial 증가.
CSR 의 SEO-critical page: 매 GoogleBot 의 partial 만 render → 매 ranking 손실.
Server Component 의 useState: 매 build error.
Client Component 의 DB query: 매 client 의 secret leak.