핵심 개념: 서버에서만 실행되고 재렌더링되지 않는 컴포넌트로, 클라이언트 번들 크기를 제로에 가깝게 줄임
실제 성과: Dagster는 RSC 도입으로 20배 속도 향상 달성
PPR의 등장: Next.js 15의 Partial Prerendering으로 정적/동적 콘텐츠의 완벽한 조화
실무 핵심: 서버 컴포넌트와 클라이언트 컴포넌트의 경계를 명확히 설계하는 것이 성공의 열쇠
왜 Server Components인가?
React 19(2024년 12월 5일 출시)는 React Server Components(RSC)를 정식 기능으로 도입했다. State of JS 2024 설문조사(14,015명 응답)에 따르면 React는 여전히 81.1%의 사용률을 기록하지만, 개발자들의 복잡성에 대한 불만도 함께 증가하고 있다.
전통적인 CSR(Client-Side Rendering)의 문제점을 살펴보자:
Plain Text
전통적인 CSR 흐름:Browser → API Request → Server → JSON Response → Browser (렌더링) ↓ 문제점: - 복잡한 상태 관리 (loading, error, data 모두 관리) - 큰 번들 크기 (데이터 처리 로직까지 클라이언트에) - 폭포수 요청 (컴포넌트 렌더링 → API 호출 → 자식 렌더링 → 다시 API 호출...)
RSC는 이 문제를 근본적으로 해결한다:
Plain Text
RSC 흐름:Browser → Server (RSC 실행 + 데이터 페칭) → 직렬화된 UI → Browser (하이드레이션) ↓ 해결: - 서버에서 데이터 처리 완료 - 클라이언트 번들 최소화 - 병렬 데이터 페칭
RSC의 핵심 개념
RSC의 핵심은 단순하다: 서버에서만 실행되며, 클라이언트로 JavaScript가 전송되지 않는 컴포넌트다.
서버 컴포넌트 vs 클라이언트 컴포넌트
| 특성 | 서버 컴포넌트 | 클라이언트 컴포넌트 |
|------|--------------|-------------------|
| 실행 위치 | 서버만 | 서버 + 클라이언트 |
| JS 번들 포함 | ❌ | ✅ |
| 상태(useState) | ❌ | ✅ |
| 이벤트 핸들러 | ❌ | ✅ |
| DB/파일 직접 접근 | ✅ | ❌ |
| async/await | ✅ | ❌ |
실전 코드: 제품 상세 페이지
이 패턴이 실제로 어떻게 적용되는지 보자:
TypeScript
// app/product/[id]/page.tsx - Server Componentinterface Product { id: string; name: string; price: number; description: string;}interface Review { id: string; rating: number; comment: string; author: string;}async function ProductPage({ params }: { params: { id: string } }) { // 서버에서만 실행 - 클라이언트에 이 코드는 전송되지 않음 // Promise.all로 병렬 페칭 - 폭포수 요청 제거 const [product, reviews] = await Promise.all([ db.products.findById(params.id) as Promise<Product>, db.reviews.findByProduct(params.id) as Promise<Review[]> ]); return ( <div className="product-container"> <h1>{product.name}</h1> {/* 정적 콘텐츠는 서버 컴포넌트로 */} <ProductDetails product={product} /> <ReviewList reviews={reviews} /> {/* 상호작용이 필요한 부분만 클라이언트로 분리 */} <AddToCartButton productId={product.id} /> </div> );}
0ms → 정적 셸 전송 (Header, Sidebar, Footer)100ms → 사용자가 레이아웃 확인 가능200ms → 동적 콘텐츠 스트리밍 시작500ms → 전체 페이지 완성vs 전통적 SSR:0ms → 서버에서 모든 데이터 페칭400ms → 렌더링 완료500ms → 한 번에 전체 HTML 전송 (그 전까지 빈 화면)