--- id: wiki-2026-0508-웹-렌더링-전략-csr-ssr-ssg-isr title: "웹 렌더링 전략 (CSR, SSR, SSG, ISR)" category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Web Rendering Strategies, CSR vs SSR, Static Generation, Incremental Static Regeneration, RSC] duplicate_of: none source_trust_level: A confidence_score: 0.93 verification_status: applied tags: [frontend, rendering, ssr, ssg, csr, isr, rsc, nextjs] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: TypeScript framework: Next.js 15, Remix, Astro 5, Qwik --- # 웹 렌더링 전략 (CSR, SSR, SSG, ISR) ## 매 한 줄 > **"매 페이지 마다 매 적절한 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) ```tsx // app/posts/page.tsx — 매 server 의 실행, 매 client JS 의 X import { db } from '@/lib/db'; export default async function PostsPage() { const posts = await db.posts.findMany({ orderBy: { createdAt: 'desc' } }); return ( ); } ``` ### Pattern 2: Client Component (interactivity) ```tsx 'use client'; import { useState } from 'react'; export function LikeButton({ postId }: { postId: string }) { const [liked, setLiked] = useState(false); return ( ); } ``` ### Pattern 3: Static Generation (SSG) ```tsx // app/blog/[slug]/page.tsx export async function generateStaticParams() { const posts = await getAllPosts(); return posts.map(p => ({ slug: p.slug })); } export default async function PostPage({ params }: { params: { slug: string } }) { const post = await getPost(params.slug); return
; } ``` ### Pattern 4: ISR (Incremental Static Regeneration) ```tsx // app/products/[id]/page.tsx export const revalidate = 3600; // 매 1시간 마다 background revalidate export default async function ProductPage({ params }) { const product = await fetchProduct(params.id); return ; } // 매 on-demand revalidation import { revalidatePath } from 'next/cache'; export async function POST(req: Request) { const { path } = await req.json(); revalidatePath(path); return Response.json({ revalidated: true }); } ``` ### Pattern 5: Streaming SSR with Suspense ```tsx import { Suspense } from 'react'; export default function Dashboard() { return ( <>
{/* 매 즉시 stream */} }> {/* 매 chunk 의 도착 시 stream */} }> ); } ``` ### Pattern 6: Astro 5 Islands ```astro --- // 매 build-time 의 server, 매 client JS 의 zero by default import Counter from './Counter.tsx'; const posts = await Astro.glob('./posts/*.md'); ---

Blog

{posts.map(p =>
{p.frontmatter.title}
)} {/* 매 viewport 의 진입 시 hydrate */} ``` ### Pattern 7: Edge Runtime (SSR at edge) ```tsx // app/api/geo/route.ts export const runtime = 'edge'; export async function GET(req: Request) { const country = req.headers.get('x-vercel-ip-country') ?? 'US'; return Response.json({ country }); } ``` ## 매 결정 기준 | 상황 | 전략 | |---|---| | Marketing / docs site | SSG (Astro, Next.js) | | E-commerce catalog | ISR (revalidate=3600) | | Personalized feed | SSR + RSC | | Real-time dashboard | CSR + SWR/React Query | | Hybrid (static shell + dynamic island) | RSC + Client Components | | Geo-aware routing | Edge SSR | | SEO + interactivity | Streaming SSR with Suspense | **기본값**: 매 Next.js 15 App Router — RSC default, Suspense streaming, ISR `revalidate` 의 사용. ## 🔗 Graph - 부모: [[웹 프론트엔드 성능 최적화|Frontend Performance Optimization (FE 성능 최적화)]] · [[React]] - 변형: [[Server Side Rendering, SSR]] · [[Static_Site_Generation_SSG|Static Site Generation (SSG)]] · [[Incremental Static Regeneration (ISR)]] · [[Modern_Web_Rendering_and_Optimization|Server Components]] - 응용: [[Next.js]] · [[Remix]] · [[Astro]] - Adjacent: [[Edge Computing]] · [[CDN]] · [[Hydration]] ## 🤖 LLM 활용 **언제**: 매 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. - **ISR 의 revalidate=1**: 매 cache 의 의미 X — 매 SSR 의 사용. ## 🧪 검증 / 중복 - Verified (Next.js 15 docs, React Server Components RFC, Patterns.dev: rendering patterns 2026). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — full spectrum (CSR/SSR/SSG/ISR/RSC), Next.js 15 patterns, decision matrix |