정의
SSR을 스트리밍으로 바꾸면 Lighthouse 점수가 오를 거라 기대할 때, 실제로 무엇이 좋아지고 무엇은 그대로인지 가르는 문서다. Streaming SSR(스트리밍 서버 렌더링)은 서버가 전체 트리를 다 준비(await)한 뒤 HTML을 한 번에 보내지 않고, shell(먼저 보내는 뼈대 HTML)과 Suspense 경계(데이터를 기다리는 동안 대체 UI를 보여주다 준비되면 채워 넣는 React 경계)를 청크(조각) 단위로 flush(내보내기) 하는 방식이다(Next.js App Router의 streaming RSC 등, RSC=React Server Component). Lighthouse(구글의 성능 측정 도구)·lab CWV(실험실 환경에서 잰 Core Web Vitals) 이득은 스트리밍 자체보다 LCP 후보(가장 큰 콘텐츠 요소)가 어느 청크에 있느냐로 결정된다.
왜 필요한가
ssr-prefetch-query-cache-hydration은 클라이언트에서 session → api/data 순으로 연쇄 요청이 이어지는 waterfall(앞 요청이 끝나야 뒤 요청이 시작되는 폭포수 지연)을 줄인다. Streaming은 다른 축이다 — 서버가 HTML 바이트를 언제 내보내기 시작하느냐. 둘을 혼동하면 "streaming만 켜면 Lighthouse가 오른다"는 잘못된 우선순위가 생긴다. auth-gated 홈(로그인 여부에 따라 내용이 갈리는 홈)처럼 LCP가 API 결과에 묶인 페이지에서는, LCP에 꼭 필요한 데이터를 뒤 Suspense로 미루면 FCP(First Contentful Paint, 첫 픽셀이 그려지는 시점)만 좋아지고 LCP는 그대로이거나 CLS(Cumulative Layout Shift, 나중에 콘텐츠가 채워지며 화면이 밀리는 정도)가 악화될 수 있다.
동작 원리
| 패턴 | 첫 바이트 / shell | LCP 요소 |
|---|---|---|
| Blocking SSR (전체 await) | 느림 (TTFB↑) | 데이터 준비 후 한 번에 paint |
| Stream, LCP late | shell 먼저 | LCP는 뒤 청크 — FCP↑, LCP≈ |
| Stream, LCP early | shell + LCP 데이터 | secondary만 defer — FCP↑, LCP↑ 가능 |
Lighthouse Performance는 LCP·TBT·CLS·FCP·SI 등을 가중 합성한 lab 점수다(lighthouse-measurement-accuracy). shell만 빨리 나와도 FCP / Speed Index는 오를 수 있고 LCP ms는 안 움직일 수 있다. 점수만 보고 “좋아졌다”고 단정하면 안 된다.
Prefetch와의 관계:
- Prefetch + hydrate — 브라우저 안 waterfall 제거.
- Streaming — 같은 서버 대기를 기다리면서도 CSS/JS 파싱·shell paint를 겹칠 여지.
- Prefetch가 이미 LCP 경로의 핵심이면, streaming의 추가 이득은 보통 부가 데이터 defer 쪽이다.
실무 적용
- LCP-critical은 앞 청크 — auth + LCP에 필요한 메타(첫 이미지 URL 등)는 blocking prefetch 또는 첫 스트림에 둔다(carousel-viewport-image-deferral).
- secondary만 Suspense — below-fold 위젯, 부가 쿼리, 비-LCP 패널을 stream defer.
- skeleton 세트 — 뒤 청크가 붙을 때 높이·행 수를 예약하지 않으면 CLS가 난다(cls-skeleton-layout-reservation).
- 측정 — Lighthouse 점수와 trace LCP ms를 분리하고, production
build && start에서 N회 median으로 before/after(lab-performance-measurement-variance).
트레이드오프
| 선택 | 이득 | 비용 |
|---|---|---|
| Blocking + LCP prefetch | LCP 경로 단순·예측 가능 | TTFB·첫 paint 지연 |
| Stream, LCP early | FCP/SI + LCP 동시 개선 가능 | 경계 설계·청크 순서 복잡도 |
| Stream, LCP late | shell·FCP 체감 | LCP 무이득·CLS 위험 |
| Prefetch만 (stream 없음) | client waterfall 제거 | shell flush 이득 없음 |
사용하면 안 되는 경우
- 공개 정적 페이지 — CDN/SSG만으로 충분한 경우.
- LCP 요소를 “나중에 채워질 자리”로만 두고 stream 이득을 LCP SLA에 기대는 경우.
- skeleton·레이아웃 예약 없이 큰 블록을 뒤 청크로 넣는 경우.
흔한 실수
- Streaming 도입 = Lighthouse Performance 자동 상승으로 가정.
- LCP-critical API를 뒤 Suspense로 미뤄 FCP만 개선된 것을 성공으로 기록.
- Prefetch와 streaming을 같은 최적화로 취급해 우선순위를 바꿈.
- 점수만 보고 LCP ms·CLS를 재측정하지 않음.
관련 개념
- ssr-prefetch-query-cache-hydration — client waterfall vs HTML flush 축
- largest-contentful-paint — LCP 후보·개선
- lighthouse-measurement-accuracy — 점수 vs trace ms
- cls-skeleton-layout-reservation — stream 청크 + skeleton
- carousel-viewport-image-deferral — LCP 메타만 early, 바이트는 defer
- lab-performance-measurement-variance — N회 median 비교