Nuxt 3와 서버 컴포넌트: 모던 웹 개발의 미래
Nuxt 3와 서버 컴포넌트: 모던 웹 개발의 미래
Vue.js 생태계의 메타 프레임워크인 Nuxt 3는 서버 사이드 렌더링(SSR), 정적 사이트 생성(SSG), 하이브리드 렌더링을 모두 지원하는 강력한 풀스택 프레임워크입니다. 특히 Nuxt 3에서 도입된 서버 컴포넌트와 Nitro 엔진은 웹 개발의 패러다임을 바꾸고 있습니다.
Nuxt 3의 핵심 혁신
1. Nitro 서버 엔진
Nuxt 3는 자체 개발한 Nitro 서버 엔진을 사용합니다. Nitro는 놀랍도록 빠르고, 어디든 배포할 수 있으며, 자동으로 최적화됩니다.
주요 특징:
- Universal Deployment: Vercel, Netlify, AWS Lambda, Cloudflare Workers 등 어디든 배포 가능
- Auto Import: API 라우트 자동 등록 및 유틸리티 자동 import
- Storage Layer: Redis, Cloudflare KV, MongoDB 등 다양한 저장소 통합
- 빠른 Cold Start: 서버리스 환경에서도 즉시 시작
// server/api/users.ts - 자동으로 /api/users 엔드포인트 생성
export default defineEventHandler(async (event) => {
const users = await prisma.user.findMany({
select: { id: true, name: true, email: true }
});
return users;
});
2. 하이브리드 렌더링
페이지마다 다른 렌더링 전략을 선택할 수 있습니다.
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true }, // 정적 생성
'/blog/**': { swr: 3600 }, // ISR (Incremental Static Regeneration)
'/dashboard/**': { ssr: false }, // CSR (클라이언트 렌더링)
'/api/**': { cors: true, headers: { 'cache-control': 's-maxage=3600' } }
}
})
이를 통해 SEO가 중요한 페이지는 SSR로, 빠른 업데이트가 필요한 페이지는 ISR로, 개인화된 대시보드는 CSR로 각각 최적화할 수 있습니다.
3. Auto Import의 마법
Nuxt 3는 Vue 컴포저블, 컴포넌트, 유틸리티를 자동으로 import합니다. 더 이상 import 문을 작성할 필요가 없습니다.
<script setup>
// ref, computed, useFetch 등 자동 import됨!
const count = ref(0)
const doubled = computed(() => count.value * 2)
const { data: users } = await useFetch('/api/users')
</script>
<template>
<!-- components/AppHeader.vue를 자동으로 찾아서 사용 -->
<AppHeader />
<div>
<p>Count: {{ count }}</p>
<p>Doubled: {{ doubled }}</p>
</div>
</template>
서버 컴포넌트의 혁명
서버 컴포넌트는 서버에서만 실행되는 컴포넌트로, 클라이언트 번들 크기를 줄이고 백엔드 리소스에 직접 접근할 수 있게 합니다.
Nuxt 서버 컴포넌트 사용법
<!-- components/ServerUserList.server.vue -->
<script setup>
import { PrismaClient } from '@prisma/client'
// 서버에서만 실행되므로 Prisma를 직접 사용 가능!
const prisma = new PrismaClient()
const users = await prisma.user.findMany({
include: { posts: true }
})
</script>
<template>
<ul>
<li v-for="user in users" :key="user.id">
{{ user.name }} - {{ user.posts.length }} posts
</li>
</ul>
</template>
이 컴포넌트는 서버에서만 렌더링되며, Prisma 코드는 클라이언트 번들에 포함되지 않습니다.
useFetch와 useAsyncData
Nuxt 3의 데이터 페칭 컴포저블은 SSR과 CSR 모두에서 완벽하게 작동합니다.
// 기본 사용법
const { data, pending, error, refresh } = await useFetch('/api/users')
// 옵션 활용
const { data: products } = await useFetch('/api/products', {
query: { category: 'electronics', limit: 10 },
transform: (data) => data.map(p => ({ ...p, price: p.price * 1000 })),
getCachedData: (key) => nuxtApp.payload.data[key],
lazy: true, // 즉시 실행하지 않음
server: false, // 서버에서 실행하지 않음
})
// 리액티브 쿼리
const page = ref(1)
const { data: paginatedUsers } = await useFetch('/api/users', {
query: { page },
watch: [page] // page가 변경되면 자동으로 재요청
})
Nuxt Layers: 코드 재사용의 새로운 차원
Nuxt Layers를 사용하면 프로젝트 구조를 여러 레이어로 분리하여 재사용할 수 있습니다.
// nuxt.config.ts
export default defineNuxtConfig({
extends: [
'@my-company/nuxt-base', // 기본 설정과 컴포넌트
'./layers/auth', // 인증 레이어
'./layers/admin', // 관리자 레이어
]
})
각 레이어는 독립적인 Nuxt 프로젝트처럼 구성되며, 컴포넌트, 컴포저블, 플러그인, 미들웨어를 공유할 수 있습니다.
Nuxt DevTools: 개발자 경험의 혁신
Nuxt 3는 강력한 DevTools를 기본 제공합니다:
- 컴포넌트 트리: 현재 페이지의 컴포넌트 구조 시각화
- 라우트 분석: 각 라우트의 렌더링 전략과 성능 측정
- API 모니터링: 서버 API 호출 추적
- 상태 관리: Pinia 스토어 상태 실시간 확인
- 성능 분석: SSR 렌더링 시간, 하이드레이션 시간 측정
Pinia와 상태 관리
Nuxt 3는 Pinia를 공식 상태 관리 라이브러리로 채택했습니다.
// stores/user.ts
export const useUserStore = defineStore('user', () => {
const user = ref(null)
const isLoggedIn = computed(() => !!user.value)
async function login(email, password) {
const { data } = await useFetch('/api/auth/login', {
method: 'POST',
body: { email, password }
})
user.value = data.value
}
return { user, isLoggedIn, login }
})
// 컴포넌트에서 사용
<script setup>
const userStore = useUserStore()
await userStore.login('user@example.com', 'password')
</script>
SEO와 메타 태그 관리
<script setup>
useSeoMeta({
title: 'My Amazing Site',
ogTitle: 'My Amazing Site',
description: 'This is my amazing site, let me tell you all about it.',
ogDescription: 'This is my amazing site, let me tell you all about it.',
ogImage: 'https://example.com/image.png',
twitterCard: 'summary_large_image',
})
useHead({
htmlAttrs: {
lang: 'ko'
},
link: [
{
rel: 'icon',
type: 'image/ico',
href: '/favicon.ico'
}
]
})
</script>
Image 최적화
Nuxt Image 모듈을 사용하면 자동으로 이미지를 최적화하고 lazy loading을 적용합니다.
<template>
<NuxtImg
src="/images/hero.jpg"
width="800"
height="600"
format="webp"
quality="80"
loading="lazy"
placeholder
/>
</template>
배포 전략
Vercel 배포
npm install
npm run build
# .output 디렉토리가 자동으로 Vercel에 배포됨
Docker 배포
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["node", ".output/server/index.mjs"]
정적 호스팅 (SSG)
npm run generate
# .output/public 디렉토리를 S3, Netlify 등에 배포
실전 프로젝트 구조
my-nuxt-app/
├── components/
│ ├── common/
│ │ ├── AppHeader.vue
│ │ └── AppFooter.vue
│ ├── features/
│ │ ├── UserProfile.vue
│ │ └── ProductCard.vue
│ └── ui/
│ ├── Button.vue
│ └── Input.vue
├── composables/
│ ├── useAuth.ts
│ ├── useCart.ts
│ └── useAnalytics.ts
├── pages/
│ ├── index.vue
│ ├── about.vue
│ ├── products/
│ │ ├── index.vue
│ │ └── [id].vue
│ └── admin/
│ └── dashboard.vue
├── server/
│ ├── api/
│ │ ├── auth/
│ │ │ ├── login.post.ts
│ │ │ └── register.post.ts
│ │ ├── products.get.ts
│ │ └── products/[id].get.ts
│ ├── middleware/
│ │ └── auth.ts
│ └── utils/
│ └── db.ts
├── stores/
│ ├── user.ts
│ └── cart.ts
├── middleware/
│ ├── auth.global.ts
│ └── admin.ts
└── nuxt.config.ts
결론
Nuxt 3는 Vue.js 생태계에서 가장 강력한 풀스택 프레임워크입니다. 서버 컴포넌트, Nitro 엔진, Auto Import, 하이브리드 렌더링 등 혁신적인 기능들이 개발자 경험과 사용자 경험을 동시에 향상시킵니다.
GMI는 Nuxt 3 기반의 현대적인 웹 애플리케이션을 설계하고 개발합니다. SEO 최적화, 성능 튜닝, 서버 인프라 구축까지 엔드투엔드 솔루션을 제공하며, 100% 온라인으로 효율적인 협업을 진행합니다.