정적과 동적은 양자택일이 아니야
웹 페이지는 빌드할 때 완성해 CDN에서 그대로 주는 쪽부터, 요청마다 서버가 새로 만들거나 브라우저가 상태를 이어 가는 쪽까지 넓은 스펙트럼 위에 있어. Next.js는 앱 전체를 한 방식에 가두지 않아. 라우트와 데이터 요청마다 알맞은 지점을 고르게 해.
| 전략 | 언제 맞는가 | 대표 사례 |
|---|---|---|
| SSG | 내용이 빌드 사이에 거의 안 바뀔 때 | 문서, 소개 페이지, 블로그 |
| ISR | 정적 속도는 필요하지만 주기적으로 새 내용이 필요할 때 | 상품, 뉴스, 가격표 |
| SSR | 쿠키나 헤더처럼 요청마다 다른 정보가 필요할 때 | 대시보드, 검색, 로그인 화면 |
| CSR | 브라우저 안에서 계속 상호작용하고 상태를 유지할 때 | 편집기, 실시간 협업 UI |
Next.js는 코드를 보고 판단해
별도의 “SSR 모드” 스위치를 먼저 고르는 방식이 아니야. cookies()나 headers()를 읽으면 요청별 렌더링이 필요하다고 판단하고, 명시적으로 캐시한 데이터는 정적으로 재사용할 수 있다고 판단해. Next.js 15부터 cookies()와 headers()는 비동기 API라서 반드시 기다린 뒤 값을 읽어야 해.
선택 기준은 신선도와 비용이야
전부 동적으로 만들면 늘 최신이지만 매 요청마다 계산 비용을 내. 전부 정적으로 만들면 빠르지만 오래된 값을 보여 줄 수 있어. “무엇이 얼마나 자주 바뀌고, 늦게 바뀌어도 되는 시간은 얼마인가?”를 라우트마다 물어봐. 기술 이름보다 이 질문이 먼저야.
라우트마다 데이터가 바뀌는 주기, 사용자별로 달라지는지, 오래된 값을 얼마나 허용할지를 표로 적어 봐. 소개 문구는 빌드 결과로 충분하고, 상품 목록은 몇 분마다 갱신해도 되며, 계정 잔액은 요청마다 읽어야 할 수 있어. 한 페이지 안에서도 Suspense와 캐시 경계로 서로 다른 전략을 조합할 수 있어. 동적 렌더링이 더 정확하고 정적 렌더링이 더 빠르다는 이분법만으로는 부족해. 정적 결과도 요청형 재검증으로 즉시 바꿀 수 있고, 동적 라우트 안의 비싼 계산도 캐시할 수 있어. 페이지 이름보다 각 데이터 조각의 수명을 기준으로 선택해야 해. 동일한 화면을 정적·재검증·요청별 방식으로 만들어 응답 header와 서버 로그를 비교해. 첫 요청, 캐시 창 안, 창 밖, 개인화 쿠키가 있는 요청에서 실제로 코드가 언제 실행되는지 확인하면 이름으로 외운 렌더링 전략이 비용의 움직임으로 바뀌어.