rendering · high priority
Streaming SSR
React 18 Suspense 기반 점진적 서버 렌더링
학습 개요
탄생 배경
쉬운 설명
복잡한 개념을 실생활 비유로 설명합니다.
“뷔페(기존 SSR) vs 코스 요리(Streaming SSR)”
뷔페(기존 SSR)는 모든 음식이 다 준비될 때까지 기다렸다가 한꺼번에 차립니다. 코스 요리(Streaming SSR)는 첫 번째 요리가 준비되는 즉시 가져다 줍니다. 손님은 마지막 디저트가 만들어지는 동안 에피타이저를 먹을 수 있습니다. 느린 API가 있어도 다른 컴포넌트를 먼저 볼 수 있습니다.
핵심 개념
기존 SSR 동작 흐름 (문제점)
데이터 패칭 완료 대기
페이지에 필요한 모든 데이터가 준비될 때까지 서버에서 기다립니다. 느린 API 하나가 전체를 블로킹합니다.
전체 HTML 생성
renderToString()으로 완성된 HTML 문자열을 한 번에 생성합니다.
한 번에 전송
완성된 HTML을 클라이언트로 한 번에 전송합니다. TTFB가 높아집니다.
Hydration 시작
전체 HTML과 JS 번들이 모두 로드된 후에야 hydration이 시작됩니다.
사용자 인터랙션 가능
전체 페이지 hydration이 완료된 후에야 사용자가 인터랙션할 수 있습니다. TTI가 높아집니다.
실무 적용
어떤 상황에서 사용하는가
Next.js App Router 대시보드 페이지에서 여러 독립적인 데이터 소스를 효율적으로 로딩
어떻게 적용하는가
각 독립적인 데이터 영역을 별도의 Suspense 경계로 감싸고, loading.tsx 또는 fallback으로 스켈레톤 UI를 제공합니다. 서버 컴포넌트에서 직접 await로 데이터를 패칭합니다.
흔한 실수와 안티패턴
- Suspense 경계를 너무 세밀하게 나누거나 너무 큰 단위로 묶어 워터폴 또는 과도한 레이아웃 시프트 발생
- 캐싱 전략 미비 - 서버 컴포넌트에서 매 요청마다 데이터 패칭 시 성능 저하
- 클라이언트 컴포넌트 남발 - "use client"를 불필요하게 사용하여 스트리밍 이점을 잃음
면접 질문
답변 방향 힌트
기존 SSR의 "모든 것을 기다려야 하는" 문제와 스트리밍의 점진적 전송을 비교하세요.
반드시 언급할 키워드
- 기존 SSR은 느린 API 하나가 전체 블로킹
- Streaming SSR은 준비된 부분부터 전송
- 낮은 TTFB, 빠른 FCP
- Suspense 경계별 독립적 로딩
예상 꼬리 질문
- Suspense 경계는 어떻게 설계하는 것이 좋나요?