엔터프라이즈급 웹 애플리케이션 개발에 있어 풀스택 프레임워크의 선택은 매우 중요합니다. Next.js와 Nuxt.js는 각각 React와 Vue.js 기반의 대표적인 풀스택 프레임워크입니다. 이 글에서는 대규모 프로젝트에서의 두 프레임워크를 비교 분석하겠습니다.
Next.js - App Router
// app/dashboard/[id]/page.tsx
export default async function DashboardPage({ params }: { params: { id: string } }) {
// 서버 컴포넌트에서 직접 데이터 fetching
const dashboard = await fetchDashboard(params.id);
return (
<main>
<DashboardHeader data={dashboard} />
<DashboardContent>
<Suspense fallback={<Loading />}>
{/* 병렬 데이터 로딩 */}
<DashboardWidgets id={params.id} />
</Suspense>
</DashboardContent>
</main>
);
}
// 정적 경로 생성
export async function generateStaticParams() {
const dashboards = await fetchDashboards();
return dashboards.map((dashboard) => ({
id: dashboard.id,
}));
}
Nuxt.js - 파일 기반 라우팅
<!-- pages/dashboard/[id].vue -->
<template>
<main>
<DashboardHeader :data="dashboard" />
<DashboardContent>
<ClientOnly>
<DashboardWidgets :id="$route.params.id" />
</ClientOnly>
</DashboardContent>
</main>
</template>
<script setup>
const route = useRoute();
const { data: dashboard } = await useFetch(
`/api/dashboards/${route.params.id}`
);
</script>
Next.js - 다양한 데이터 페칭 전략
// 서버 사이드 데이터 페칭
async function ProductList() {
const products = await fetchProducts();
return <ProductGrid products={products} />;
}
// 클라이언트 사이드 데이터 페칭
'use client';
function ProductSearch() {
const { data, isLoading } = useQuery({
queryKey: ['products', searchTerm],
queryFn: () => fetchProducts(searchTerm)
});
return isLoading ? <Loading /> : <SearchResults data={data} />;
}
// API 라우트
// app/api/products/route.ts
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const products = await db.products.findMany({
where: { category: searchParams.get('category') }
});
return Response.json(products);
}
Nuxt.js - 통합된 데이터 페칭
// composables/useProducts.ts
export const useProducts = () => {
return useFetch('/api/products', {
key: 'products',
transform: (response) => response.data,
watch: [/* 의존성 */]
});
}
// server/api/products.ts
export default defineEventHandler(async (event) => {
const query = getQuery(event);
const products = await db.products.findMany({
where: { category: query.category }
});
return products;
});
// Next.js의 성능 최적화 예시
// 이미지 자동 최적화
import Image from 'next/image';
function ProductImage({ product }) {
return (
<Image
src={product.image}
alt={product.name}
width={800}
height={600}
placeholder="blur"
quality={75}
/>
);
}
// Streaming SSR
export default async function ProductPage() {
return (
<Suspense fallback={<Loading />}>
<ProductInfo />
<Suspense fallback={<RelatedProductsSkeleton />}>
<RelatedProducts />
</Suspense>
</Suspense>
);
}
// Next.js의 미들웨어 예시
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('token');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
// A/B 테스팅 구현
if (request.nextUrl.pathname === '/products') {
const bucket = Math.random() > 0.5 ? 'A' : 'B';
const response = NextResponse.next();
response.cookies.set('test-bucket', bucket);
return response;
}
}
export const config = {
matcher: ['/dashboard/:path*', '/products/:path*'],
};
대규모 프로젝트에서 Next.js는 다음과 같은 이점을 제공합니다:
엔터프라이즈급 성능
강력한 개발자 경험
높은 확장성
Nuxt.js도 훌륭한 프레임워크이지만, 대규모 프로젝트의 요구사항과 장기적인 확장성을 고려할 때 Next.js가 더 적합한 선택이 될 것입니다. 특히 React 생태계의 성숙도와 Server Components와 같은 혁신적인 기능들은 엔터프라이즈 애플리케이션 개발에 있어 큰 이점을 제공합니다.