Files
nuxt-deep/docs/curriculum/01-rendering-strategy.md

5.0 KiB

1. 렌더링 방식 + 배포 환경 선택 전략

Nuxt 4 기준으로 작성됨 (2026-03)

렌더링 전략 개요

Nuxt는 네 가지 렌더링 전략을 지원한다. nuxt.config.ts 설정만으로 전환 가능하다.

전략 설명 주요 사용 사례
SSR (Server-Side Rendering) 요청마다 서버에서 HTML 생성 실시간 데이터, SEO가 중요한 페이지
SSG (Static Site Generation) 빌드 시 HTML 미리 생성 블로그, 문서, 변경이 적은 콘텐츠
SPA (Single Page Application) 클라이언트에서만 렌더링 인증 이후 대시보드, 관리자 페이지
Hybrid 페이지마다 다른 전략 적용 복합 요구사항을 가진 앱

nuxt.config.ts 핵심 옵션

전역 렌더링 모드 설정

// nuxt.config.ts
export default defineNuxtConfig({
  // SSR 활성화 여부 (기본값: true)
  ssr: true,

  app: {
    head: {
      title: '앱 제목',
      meta: [{ name: 'description', content: '설명' }]
    }
  },

  // 런타임 환경변수 (서버/클라이언트 구분)
  runtimeConfig: {
    // 서버에서만 접근 가능
    apiSecret: process.env.API_SECRET,
    // 클라이언트에도 노출됨 (public)
    public: {
      apiBase: process.env.API_BASE_URL
    }
  },

  // Nitro 서버 엔진 설정
  nitro: {
    preset: 'node-server', // 배포 환경에 따라 변경
  },

  // 라우트별 개별 전략 (Hybrid 렌더링)
  routeRules: {
    '/admin/**': { ssr: false },          // SPA로 처리
    '/blog/**': { prerender: true },       // SSG로 미리 생성
    '/api/**': { cors: true },             // API 라우트 CORS 허용
    '/products/**': { swr: 3600 },        // SWR: 1시간 캐시, 백그라운드 재생성
    '/dashboard': { isr: 60 },            // ISR: 60초 캐시 (CDN 지원 플랫폼)
  }
})

전략별 선택 기준

SSR을 선택해야 할 때

  • 검색엔진 최적화(SEO)가 필요한 공개 페이지
  • 사용자마다 다른 데이터를 보여줘야 할 때 (개인화된 피드 등)
  • 실시간으로 자주 바뀌는 데이터 (재고, 가격 등)
// 기본값이 ssr: true이므로 별도 설정 불필요
export default defineNuxtConfig({
  ssr: true
})

SSG를 선택해야 할 때

  • 변경이 드문 콘텐츠 (블로그, 마케팅 페이지)
  • CDN 캐시 최대 활용이 필요한 경우
  • 서버 운영 비용을 최소화하고 싶을 때
// 빌드 시 모든 페이지를 미리 생성
export default defineNuxtConfig({
  routeRules: {
    '/**': { prerender: true }
  }
})

SPA를 선택해야 할 때

  • 로그인 후에만 접근하는 페이지 (SEO 불필요)
  • 복잡한 인터랙션이 많은 대시보드
  • API 서버를 별도로 운영하고 있을 때
export default defineNuxtConfig({
  ssr: false // 전체를 SPA로
  // 또는 routeRules로 특정 경로만 SPA
})

Hybrid (SWR / ISR 포함)를 선택해야 할 때

  • 페이지마다 요구사항이 다를 때
  • 대부분 정적이지만 일부 페이지는 SSR이 필요할 때
export default defineNuxtConfig({
  routeRules: {
    '/': { prerender: true },           // 홈: SSG
    '/products/**': { swr: 3600 },      // 상품: SWR 1시간 캐시 + 백그라운드 재생성
    '/blog': { isr: 3600 },            // 블로그: ISR (CDN 캐시, Vercel/Netlify)
    '/blog/**': { isr: true },          // 글: 다음 배포까지 CDN에 캐시
    '/cart': { ssr: false },            // 장바구니: SPA
    '/checkout': { ssr: true },         // 결제: SSR (실시간)
    '/old-page': { redirect: '/new-page' }, // 리다이렉트
  }
})

SEO 최적화와 캐시 전략

SEO를 위한 메타태그 설정

// pages/products/[id].vue
definePageMeta({
  title: '상품 상세'
})

// 또는 useHead()로 동적 설정
useHead({
  title: computed(() => product.value?.name),
  meta: [
    { name: 'description', content: computed(() => product.value?.description) }
  ]
})

// useSeoMeta() — 타입 안전한 방식 (권장)
useSeoMeta({
  title: '상품명',
  ogTitle: '상품명',
  description: '상품 설명',
  ogImage: '/og-image.png'
})

routeRules를 활용한 캐시 전략

routeRules: {
  // CDN에 1시간 캐시
  '/blog/**': {
    prerender: true,
    headers: { 'cache-control': 's-maxage=3600' }
  },
  // SWR: 서버/리버스 프록시에서 캐시, 만료 후 백그라운드 재생성
  '/products/**': { swr: 3600 },
  // ISR: CDN 플랫폼(Vercel, Netlify)에서 캐시, 만료 후 재생성
  '/deals/**': { isr: 60 },
  // 캐시 완전 비활성화
  '/api/live/**': { headers: { 'cache-control': 'no-store' } }
}

배포 환경별 Nitro preset

nitro: {
  preset: 'vercel'        // Vercel
  preset: 'netlify'       // Netlify
  preset: 'cloudflare'    // Cloudflare Workers
  preset: 'node-server'   // Node.js 서버 (기본)
  preset: 'static'        // 정적 파일로 빌드
}

NITRO_PRESET 환경변수로도 설정 가능하다. 배포 플랫폼에 맞게 자동 감지되는 경우가 많다.