본문 바로가기
Frontend2026년 5월 20일3분 읽기

Next.js 16 PPR — Partial Prerendering 프로덕션 3개월 운영기

YS
김영삼
조회 435
Next.js 16 PPR — Partial Prerendering 프로덕션 3개월 운영기

핵심 요약

Next.js 16에서 PPR이 stable로 풀린 직후 사내 커머스 앱(월 850만 PV)에 적용. LCP p75 1.4s → 0.6s, TTFB p75 480ms → 110ms. 정적 셸이 즉시 도착하고 사용자별 영역만 스트리밍되는 모델이 광고가 많은 페이지에서 효과 압도적.

1. 모델

페이지를 두 영역으로: 정적 셸(헤더·푸터·레이아웃) + 동적 hole(추천·재고·장바구니). 셸은 빌드 시 prerender, hole은 요청 시 스트리밍. 사용자가 첫 픽셀을 즉시 본다.

2. 활성화

// next.config.js
module.exports = { experimental: { ppr: true } }

// page.tsx
import { Suspense } from 'react';
export default async function Page() {
  return (
    <Layout>
      <Suspense fallback={<Skeleton/>}>
        <UserPanel />{/* 동적 hole */}
      </Suspense>
    </Layout>
  );
}

3. 측정 — Before/After

지표
LCP p751.4s0.6s
TTFB p75480ms110ms
CDN 캐시 hit62%89%
서버 비용/월$4,200$1,800

4. 함정 1 — Suspense 경계 위치

너무 작으면 깜빡임 다발, 너무 크면 효과 없음. 사용자별·세션별 데이터 단위로 묶는 게 정답. 헤더 안 알림 뱃지, 카드 안 가격 같은 작은 hole은 묶어서 1~2개로.

5. 함정 2 — cookies()/headers() 사용

이 API를 호출하는 컴포넌트는 자동으로 동적 처리됨. 의도와 다르게 페이지 전체가 동적이 되어버리는 사례 다수. 호출은 정말 필요한 컴포넌트로 격리.

6. CDN 설정

Cloudflare/Vercel 모두 PPR 셸을 long-cache(1d), hole은 cache 우회 헤더. cache-control: s-maxage=86400, stale-while-revalidate=604800 권장.

7. 모니터링

Web Vitals API + Real User Monitoring(RUM). LCP 95th 회귀를 PR마다 측정. next-bundle-analyzer로 클라이언트 번들 회귀도 같이.

자주 묻는 질문

Q. App Router 외 페이지 라우터는? PPR은 App Router 전용. 페이지 라우터 사용자는 점진 이전이 사실상 강제.

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록