nuxt logo

문서 번역(비공식)

Nuxt.js
Version:v3.17

렌더링 모드

Nuxt에서 사용할 수 있는 다양한 렌더링 모드에 대해 알아보세요.

Nuxt는 다양한 렌더링 모드를 지원합니다. 유니버설 렌더링, 클라이언트 사이드 렌더링뿐만 아니라 하이브리드 렌더링CDN 엣지 서버에서 애플리케이션을 렌더링할 수 있는 가능성도 제공합니다.

브라우저와 서버 모두 JavaScript 코드를 해석하여 Vue.js 컴포넌트를 HTML 요소로 변환할 수 있습니다. 이 단계는 렌더링이라고 불립니다. Nuxt는 유니버설클라이언트 사이드 렌더링을 모두 지원합니다. 두 가지 접근 방식에는 장점과 단점이 있으며, 이를 다룰 것입니다.

기본적으로 Nuxt는 유니버설 렌더링을 사용하여 더 나은 사용자 경험, 성능을 제공하고 검색 엔진 인덱싱을 최적화하지만, 한 줄의 설정으로 렌더링 모드를 전환할 수 있습니다.

유니버설 렌더링

이 단계는 PHP나 Ruby 애플리케이션에서 수행되는 전통적인 서버 사이드 렌더링과 유사합니다. 브라우저가 유니버설 렌더링이 활성화된 URL을 요청하면, Nuxt는 서버 환경에서 JavaScript (Vue.js) 코드를 실행하고 완전히 렌더링된 HTML 페이지를 브라우저에 반환합니다. Nuxt는 또한 사전에 생성된 페이지가 있는 경우 캐시에서 완전히 렌더링된 HTML 페이지를 반환할 수 있습니다. 사용자는 클라이언트 사이드 렌더링과 달리 애플리케이션의 초기 콘텐츠 전체를 즉시 얻습니다.

HTML 문서가 다운로드되면 브라우저는 이를 해석하고 Vue.js가 문서를 제어합니다. 서버에서 실행되었던 동일한 JavaScript 코드가 이제 클라이언트(브라우저)에서 다시 백그라운드에서 실행되어 HTML에 리스너를 바인딩하여 상호작용을 가능하게 합니다(따라서 유니버설 렌더링). 이를 하이드레이션이라고 합니다. 하이드레이션이 완료되면 페이지는 동적 인터페이스와 페이지 전환과 같은 이점을 누릴 수 있습니다.

유니버설 렌더링은 Nuxt 애플리케이션이 클라이언트 사이드 렌더링의 이점을 유지하면서 빠른 페이지 로드 시간을 제공할 수 있게 합니다. 또한, 콘텐츠가 이미 HTML 문서에 존재하기 때문에 크롤러가 이를 오버헤드 없이 인덱싱할 수 있습니다.

사용자는 HTML 문서가 로드될 때 정적 콘텐츠에 접근할 수 있습니다. 하이드레이션은 페이지의 상호작용을 가능하게 합니다

서버에서 렌더링되는 것과 클라이언트에서 렌더링되는 것은 무엇인가요?

유니버설 렌더링 모드에서 Vue 파일의 어느 부분이 서버와/또는 클라이언트에서 실행되는지 궁금해하는 것은 당연합니다.

app.vue
<script setup lang="ts">
const counter = ref(0); // 서버와 클라이언트 환경에서 실행됩니다.

const handleClick = () => {
  counter.value++; // 클라이언트 환경에서만 실행됩니다.
};
</script>

<template>
  <div>
    <p>Count: {{ counter }}</p>
    <button @click="handleClick">Increment</button>
  </div>
</template>

초기 요청 시, counter ref는 <p> 태그 안에서 렌더링되기 때문에 서버에서 초기화됩니다. handleClick의 내용은 여기서 절대 실행되지 않습니다. 브라우저에서 하이드레이션 중에 counter ref는 다시 초기화됩니다. handleClick은 마침내 버튼에 바인딩됩니다. 따라서 handleClick의 본문은 항상 브라우저 환경에서 실행된다고 추론하는 것이 합리적입니다.

미들웨어페이지는 하이드레이션 중에 서버와 클라이언트에서 실행됩니다. 플러그인은 서버 또는 클라이언트 또는 둘 다에서 렌더링될 수 있습니다. 컴포넌트는 클라이언트에서만 실행되도록 강제할 수도 있습니다. 컴포저블유틸리티는 사용 맥락에 따라 렌더링됩니다.

서버 사이드 렌더링의 장점:

  • 성능: 사용자는 브라우저가 JavaScript로 생성된 콘텐츠보다 정적 콘텐츠를 훨씬 빠르게 표시할 수 있기 때문에 페이지의 콘텐츠에 즉시 접근할 수 있습니다. 동시에 Nuxt는 하이드레이션 과정에서 웹 애플리케이션의 상호작용성을 유지합니다.
  • 검색 엔진 최적화: 유니버설 렌더링은 페이지의 전체 HTML 콘텐츠를 브라우저에 클래식 서버 애플리케이션처럼 전달합니다. 웹 크롤러는 페이지의 콘텐츠를 직접 인덱싱할 수 있어, 유니버설 렌더링은 빠르게 인덱싱하고자 하는 콘텐츠에 적합한 선택입니다.

서버 사이드 렌더링의 단점:

  • 개발 제약: 서버와 브라우저 환경은 동일한 API를 제공하지 않으며, 양쪽에서 원활하게 실행될 수 있는 코드를 작성하는 것은 까다로울 수 있습니다. 다행히도 Nuxt는 코드가 어디에서 실행되는지를 결정하는 데 도움이 되는 가이드라인과 특정 변수를 제공합니다.
  • 비용: 페이지를 실시간으로 렌더링하려면 서버가 실행되어야 합니다. 이는 전통적인 서버와 마찬가지로 월간 비용을 추가합니다. 그러나 브라우저가 클라이언트 사이드 탐색을 인계받기 때문에 유니버설 렌더링 덕분에 서버 호출이 크게 줄어듭니다. 엣지 사이드 렌더링을 활용하여 비용 절감이 가능합니다.

유니버설 렌더링은 매우 다재다능하며 거의 모든 사용 사례에 적합하며, 특히 콘텐츠 중심의 웹사이트에 적합합니다: 블로그, 마케팅 웹사이트, 포트폴리오, 전자상거래 사이트, 마켓플레이스.

하이드레이션 불일치 없이 Vue 코드를 작성하는 방법에 대한 더 많은 예시는 Vue 문서를 참조하세요.

브라우저 API에 의존하고 부작용이 있는 라이브러리를 가져올 때, 이를 가져오는 컴포넌트가 클라이언트 사이드에서만 호출되도록 해야 합니다. 번들러는 부작용이 있는 모듈의 import를 트리쉐이킹하지 않습니다.

클라이언트 사이드 렌더링

기본적으로 전통적인 Vue.js 애플리케이션은 브라우저(또는 클라이언트)에서 렌더링됩니다. 그런 다음 Vue.js는 브라우저가 현재 인터페이스를 생성하기 위한 지침을 포함한 모든 JavaScript 코드를 다운로드하고 구문 분석한 후 HTML 요소를 생성합니다.

사용자는 브라우저가 JavaScript를 다운로드, 구문 분석 및 실행할 때까지 페이지의 콘텐츠를 볼 수 없습니다

클라이언트 사이드 렌더링의 장점:

  • 개발 속도: 클라이언트 사이드에서만 작업할 때는 window 객체와 같은 브라우저 전용 API를 사용하여 코드의 서버 호환성을 걱정할 필요가 없습니다.
  • 저렴함: 서버를 실행하는 것은 JavaScript를 지원하는 플랫폼에서 실행해야 하므로 인프라 비용을 추가합니다. 우리는 HTML, CSS, JavaScript 파일이 있는 모든 정적 서버에 클라이언트 전용 애플리케이션을 호스팅할 수 있습니다.
  • 오프라인: 코드가 브라우저에서 완전히 실행되기 때문에 인터넷이 없을 때도 잘 작동할 수 있습니다.

클라이언트 사이드 렌더링의 단점:

  • 성능: 사용자는 브라우저가 JavaScript 파일을 다운로드, 구문 분석 및 실행할 때까지 기다려야 합니다. 다운로드 부분은 네트워크에, 구문 분석 및 실행은 사용자의 장치에 따라 시간이 걸릴 수 있으며, 이는 사용자의 경험에 영향을 미칠 수 있습니다.
  • 검색 엔진 최적화: 클라이언트 사이드 렌더링을 통해 제공되는 콘텐츠를 인덱싱하고 업데이트하는 데는 서버 렌더링된 HTML 문서보다 더 많은 시간이 걸립니다. 이는 우리가 논의한 성능 단점과 관련이 있으며, 검색 엔진 크롤러는 페이지를 인덱싱하려고 할 때 인터페이스가 완전히 렌더링될 때까지 기다리지 않습니다. 순수 클라이언트 사이드 렌더링으로는 콘텐츠가 검색 결과 페이지에 표시되고 업데이트되는 데 더 많은 시간이 걸립니다.

클라이언트 사이드 렌더링은 인덱싱이 필요 없거나 사용자가 자주 방문하는 대화형 웹 애플리케이션에 적합한 선택입니다. 브라우저 캐싱을 활용하여 후속 방문 시 다운로드 단계를 건너뛸 수 있습니다. 예를 들어 SaaS, 백오피스 애플리케이션, 온라인 게임 등이 있습니다.

Nuxt에서 nuxt.config.ts 파일을 통해 클라이언트 사이드 전용 렌더링을 활성화할 수 있습니다:

nuxt.config.ts
export default defineNuxtConfig({
  ssr: false
})

ssr: false를 사용하는 경우, 앱이 하이드레이션될 때까지 렌더링할 로딩 화면을 포함할 HTML 파일을 ~/app/spa-loading-template.html에 배치해야 합니다.

이것도 참고 SPA 로딩 템플릿

정적 클라이언트 렌더링 앱 배포

nuxt generate 또는 nuxt build --prerender 명령어로 정적 호스팅에 앱을 배포하면 기본적으로 Nuxt는 모든 페이지를 별도의 정적 HTML 파일로 렌더링합니다.

nuxt generate 또는 nuxt build --prerender 명령어로 앱을 사전 렌더링하면 출력 폴더에 서버가 포함되지 않으므로 서버 엔드포인트를 사용할 수 없습니다. 서버 기능이 필요하면 nuxt build를 사용하세요.

순수 클라이언트 사이드 렌더링을 사용하는 경우, 이는 불필요할 수 있습니다. 모든 요청에 대해 정적 웹 호스트가 제공할 수 있는 단일 index.html 파일과 200.html, 404.html 폴백만 필요할 수 있습니다.

이를 달성하기 위해 경로가 사전 렌더링되는 방식을 변경할 수 있습니다. nuxt.config.ts후크에 다음을 추가하세요:

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'prerender:routes' ({ routes }) {
      routes.clear() // 기본값을 제외한 경로를 생성하지 않습니다.
    }
  },
})

이렇게 하면 세 개의 파일이 생성됩니다:

  • index.html
  • 200.html
  • 404.html

200.html404.html은 사용 중인 호스팅 제공업체에 유용할 수 있습니다.

클라이언트 폴백 생성 건너뛰기

클라이언트 렌더링 앱을 사전 렌더링할 때, Nuxt는 기본적으로 index.html, 200.html, 404.html 파일을 생성합니다. 그러나 빌드에서 이러한 파일 중 일부(또는 전부)를 생성하지 않으려면 Nitro'prerender:generate' 후크를 사용할 수 있습니다.

nuxt.config.ts
export default defineNuxtConfig({
  ssr: false,
  nitro: {
    hooks: {
      'prerender:generate'(route) {
        const routesToSkip = ['/index.html', '/200.html', '/404.html']
        if (routesToSkip.includes(route.route)) {
          route.skip = true
        }
      }
    }
  }
})

하이브리드 렌더링

하이브리드 렌더링은 경로 규칙을 사용하여 경로별로 다른 캐싱 규칙을 허용하고 주어진 URL에 대한 새로운 요청에 서버가 어떻게 응답해야 하는지를 결정합니다.

이전에는 Nuxt 애플리케이션과 서버의 모든 경로/페이지가 유니버설 또는 클라이언트 사이드와 같은 동일한 렌더링 모드를 사용해야 했습니다. 다양한 경우에 일부 페이지는 빌드 시에 생성될 수 있는 반면, 다른 페이지는 클라이언트 사이드에서 렌더링되어야 합니다. 예를 들어, 관리자 섹션이 있는 콘텐츠 웹사이트를 생각해 보세요. 모든 콘텐츠 페이지는 주로 정적이어야 하며 한 번 생성되지만, 관리자 섹션은 등록이 필요하며 더 동적 애플리케이션처럼 작동합니다.

Nuxt는 경로 규칙과 하이브리드 렌더링 지원을 포함합니다. 경로 규칙을 사용하여 nuxt 경로 그룹에 대한 규칙을 정의하고, 렌더링 모드를 변경하거나 경로에 따라 캐시 전략을 할당할 수 있습니다!

Nuxt 서버는 자동으로 해당 미들웨어를 등록하고 Nitro 캐싱 레이어를 사용하여 캐시 핸들러로 경로를 래핑합니다.

nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // 홈페이지는 빌드 시에 사전 렌더링됩니다.
    '/': { prerender: true },
    // 제품 페이지는 필요에 따라 생성되며, 백그라운드에서 재검증되며, API 응답이 변경될 때까지 캐시됩니다.
    '/products': { swr: true },
    // 제품 페이지는 필요에 따라 생성되며, 백그라운드에서 재검증되며, 1시간(3600초) 동안 캐시됩니다.
    '/products/**': { swr: 3600 },
    // 블로그 게시물 페이지는 필요에 따라 생성되며, 백그라운드에서 재검증되며, CDN에서 1시간(3600초) 동안 캐시됩니다.
    '/blog': { isr: 3600 },
    // 블로그 게시물 페이지는 배포될 때까지 한 번 생성되며, CDN에 캐시됩니다.
    '/blog/**': { isr: true },
    // 관리자 대시보드는 클라이언트 사이드에서만 렌더링됩니다.
    '/admin/**': { ssr: false },
    // API 경로에 cors 헤더를 추가합니다.
    '/api/**': { cors: true },
    // 레거시 URL을 리디렉션합니다.
    '/old-page': { redirect: '/new-page' }
  }
})

경로 규칙

사용할 수 있는 다양한 속성은 다음과 같습니다:

  • redirect: string - 서버 사이드 리디렉션을 정의합니다.
  • ssr: boolean - 앱의 일부 섹션에 대한 HTML의 서버 사이드 렌더링을 비활성화하고 ssr: false로 브라우저에서만 렌더링합니다.
  • cors: boolean - cors: true로 자동으로 cors 헤더를 추가합니다. headers로 출력물을 재정의하여 사용자 정의할 수 있습니다.
  • headers: object - 사이트의 특정 섹션에 헤더를 추가합니다. 예를 들어, 자산에 대한 헤더를 추가할 수 있습니다.
  • swr: number | boolean - 서버 응답에 캐시 헤더를 추가하고 서버 또는 리버스 프록시에 구성 가능한 TTL(수명 시간) 동안 캐시합니다. Nitro의 node-server 프리셋은 전체 응답을 캐시할 수 있습니다. TTL이 만료되면 캐시된 응답이 전송되며, 페이지는 백그라운드에서 재생성됩니다. true가 사용되면 MaxAge 없이 stale-while-revalidate 헤더가 추가됩니다.
  • isr: number | boolean - swr과 동일한 동작을 하며, 이를 통해 CDN 캐시에 응답을 추가할 수 있습니다(현재 Netlify 또는 Vercel에서 지원). true가 사용되면 콘텐츠는 CDN 내에서 다음 배포까지 유지됩니다.
  • prerender: boolean - 빌드 시 경로를 사전 렌더링하고 정적 자산으로 빌드에 포함합니다.
  • noScripts: boolean - 사이트의 일부 섹션에 대한 Nuxt 스크립트 및 JS 리소스 힌트 렌더링을 비활성화합니다.
  • appMiddleware: string | string[] | Record<string, boolean> - 애플리케이션의 Vue 앱 부분(즉, Nitro 경로가 아닌) 내의 페이지 경로에 대해 실행되거나 실행되지 않아야 하는 미들웨어를 정의할 수 있습니다.

가능한 경우, 경로 규칙은 최적의 성능을 위해 배포 플랫폼의 네이티브 규칙에 자동으로 적용됩니다(현재 Netlify와 Vercel이 지원됩니다).

하이브리드 렌더링은 nuxt generate를 사용할 때 사용할 수 없습니다.

예시:

엣지 사이드 렌더링

엣지 사이드 렌더링(ESR)은 Nuxt에서 도입된 강력한 기능으로, 콘텐츠 전송 네트워크(CDN)의 엣지 서버를 통해 Nuxt 애플리케이션을 사용자에게 더 가깝게 렌더링할 수 있습니다. ESR을 활용하면 성능이 향상되고 지연 시간이 줄어들어 향상된 사용자 경험을 제공할 수 있습니다.

ESR을 사용하면 렌더링 프로세스가 네트워크의 '엣지', 즉 CDN의 엣지 서버로 이동합니다. ESR은 실제 렌더링 모드라기보다는 배포 대상에 가깝습니다.

페이지에 대한 요청이 있을 때, 원래 서버로 가는 대신 가장 가까운 엣지 서버에서 가로챕니다. 이 서버는 페이지의 HTML을 생성하여 사용자에게 반환합니다. 이 프로세스는 데이터가 이동해야 하는 물리적 거리를 최소화하여 지연 시간을 줄이고 페이지를 더 빠르게 로드합니다.

엣지 사이드 렌더링은 Nuxt를 구동하는 서버 엔진Nitro 덕분에 가능합니다. Node.js, Deno, Cloudflare Workers 등 다양한 플랫폼을 지원합니다.

현재 ESR을 활용할 수 있는 플랫폼은 다음과 같습니다:

  • Cloudflare Pages - git 통합 및 nuxt build 명령어를 사용하여 설정 없이 사용 가능
  • Vercel Edge Functions - nuxt build 명령어와 NITRO_PRESET=vercel-edge 환경 변수를 사용
  • Netlify Edge Functions - nuxt build 명령어와 NITRO_PRESET=netlify-edge 환경 변수를 사용

하이브리드 렌더링은 경로 규칙과 함께 엣지 사이드 렌더링을 사용할 때 사용할 수 있습니다.

위에서 언급한 플랫폼 중 일부에 배포된 오픈 소스 예제를 탐색할 수 있습니다: