렌더링 모드(Rendering Modes)

렌더링 모드(Rendering Modes)

Nuxt는 브라우저와 서버 양쪽에서 JavaScript(Vue.js) 코드를 해석해 Vue 컴포넌트를 HTML 요소로 바꿀 수 있어요. 이 과정을 렌더링(rendering) 이라고 하고, Nuxt는 크게 유니버설 렌더링(universal)클라이언트 사이드 렌더링(client-side) 을 지원해요. 기본은 유니버설 렌더링이고, 설정 한 줄로 바꿀 수 있어요. 각 모드의 장단점을 정리할게요.

출처: https://nuxt.com/docs/4.x/guide/concepts/rendering

유니버설 렌더링(Universal Rendering)

이 방식은 전통적인 Server-Side Rendering(SSR)과 비슷해요. 브라우저가 URL을 요청하면 Nuxt가 서버 환경에서 Vue 코드를 실행하고 완전히 렌더링된 HTML 페이지를 돌려줘요. 미리 생성된 페이지면 캐시에서 HTML을 반환할 수도 있어요. 사용자는 첫 화면에서 애플리케이션의 초기 콘텐츠 전체를 바로 얻게 되죠.

HTML 문서가 다운로드되면 브라우저가 해석하고 Vue.js가 문서를 제어해요. 서버에서 실행됐던 같은 JavaScript 코드가 클라이언트(브라우저)에서 다시 실행되면서 리스너를 HTML에 바인딩해 상호작용을 가능하게 하는데, 이게 하이드레이션(Hydration) 이에요.

무엇이 서버에서 렌더링되고, 무엇이 클라이언트에서 렌더링되는지 궁금할 수 있어요.

초기 요청에서 counter ref는 <p> 태그 안에서 렌더링되므로 서버에서 초기화돼요. handleClick 함수 본문은 이 시점에 실행되지 않아요. 브라우저에서 하이드레이션되는 동안 counter ref는 다시 초기화되고, handleClick은 버튼에 바인딩돼요. 그래서 handleClick 본문은 항상 브라우저 환경에서 실행된다고 볼 수 있어요.

서버 렌더링의 장점:

  • 성능: 브라우저가 정적 콘텐츠를 JavaScript 생성 콘텐츠보다 훨씬 빨리 표시하므로 사용자가 즉시 콘텐츠에 접근할 수 있어요.
  • SEO: 페이지의 모든 HTML 콘텐츠가 전달되므로 크롤러가 오버헤드 없이 바로 인덱싱할 수 있어요.

서버 렌더링의 단점:

  • 개발 제약: 서버와 브라우저는 같은 API를 제공하지 않아 양쪽 모두에서 동작하는 코드를 작성하기 까다로워요.
  • 비용: 페이지를 실시간 렌더링하려면 서버가 계속 실행돼야 해요.

유니버설 렌더링은 거의 모든 유스케이스에 맞는 블로그, 마케팅 사이트, 포트폴리오, 이커머스, 마켓플레이스 같은 콘텐츠 중심 웹사이트에 특히 적합해요.

클라이언트 사이드 렌더링(Client-Side Rendering, CSR)

전통적인 Vue.js 앱은 브라우저(클라이언트)에서 렌더링돼요. 브라우저가 인터페이스를 만들기 위한 코드를 담은 JavaScript를 모두 다운로드·파싱한 뒤에 Vue가 HTML 요소를 생성해요.

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

  • 개발 속도: window 객체 같은 브라우저 전용 API를 자유롭게 쓸 수 있어요.
  • 비용 절감: 정적 서버에 HTML/CSS/JS 파일만 호스팅하면 되니 인프라 비용이 낮아요.
  • 오프라인: 코드가 전부 브라우저에서 실행되므로 인터넷이 끊겨도 계속 동작해요.

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

  • 성능: JavaScript를 다운로드·파싱·실행할 때까지 사용자가 기다려야 해요.
  • SEO: 콘텐츠 인덱싱·업데이트가 서버 렌더링 HTML보다 오래 걸려요.

클라이언트 렌더링은 인덱싱이 필요 없는, 사용자가 자주 방문하는 고도로 상호작용적인 웹 애플리케이션(SaaS, 백오피스, 온라인 게임)에 좋아요.

nuxt.config.ts에서 ssr: false로 설정하면 클라이언트 전용 렌더링을 켤 수 있어요.

export default defineNuxtConfig({
  ssr: false,
})

ssr: false를 쓰면 앱이 하이드레이션될 때까지 로딩 화면으로 표시할 HTML을 ~/spa-loading-template.html에 넣어두는 것도 권장해요.

하이브리드 렌더링(Hybrid Rendering)

하이브리드 렌더링은 Route Rules로 라우트마다 다른 캐싱·렌더링 규칙을 적용할 수 있게 해줘요. 예를 들어 콘텐츠 사이트에서 모든 콘텐츠 페이지는 빌드 때 한 번 생성해 정적으로 두고, 관리자 섹션은 클라이언트 렌더링으로 동적 앱처럼 동작하게 할 수 있어요. Nuxt 서버는 해당 라우트에 캐시 핸들러를 자동으로 등록해요.

route rules는 라우트 그룹에 대해 렌더링 모드를 바꾸거나 캐시 전략을 지정해요:

  • ssr: booleanssr: false로 특정 영역을 브라우저에서만 렌더링
  • cors: booleancors: true로 자동으로 CORS 헤더 추가
  • headers: object — 특정 영역에 헤더 추가
  • swr: number|boolean — 서버 응답에 캐시 헤더를 추가하고 설정한 TTL 동안 캐시
  • isr: number|booleanswr와 같지만 지원 플랫폼(Netlify·Vercel)에서 CDN 캐시에도 추가
  • prerender: boolean — 빌드 때 라우트 프리렌더링해 정적 자산으로 포함
  • noScripts: boolean — 해당 영역의 Nuxt 스크립트 렌더링 비활성화

isr이나 swr를 쓰는 라우트는 HTML 옆에 _payload.json 파일도 생성해, 클라이언트 내비게이션이 데이터를 다시 가져오는 대신 캐시된 페이로드를 로드해요. 동적 라우트는 '/**': { isr: true } 같은 glob 패턴으로 설정할 수 있어요.

에지 사이드 렌더링(Edge-Side Rendering, ESR)

Edge-Side Rendering(ESR)은 렌더링을 사용자와 가장 가까운 CDN의 에지 서버로 옮겨 성능을 높이고 지연 시간을 줄여주는 기능이에요. 요청이 원본 서버까지 가지 않고 가장 가까운 에지 서버가 HTML을 생성해 반환하므로 물리적 거리가 줄어 페이지가 더 빨리 로드돼요.

ESR은 Nuxt를 구동하는 서버 엔진인 Nitro 덕분에 가능하며, Node.js·Deno·Cloudflare Workers 등 크로스 플랫폼을 지원해요. 현재 Cloudflare Pages, Vercel Cloud, Netlify Edge Functions에서 활용할 수 있어요.

더 알아보기