Next.js 14와 Server Actions 도입 후기: 실제 프로덕션 경험 공유
2025년 초, 실제 프로덕션 환경에 Next.js 14를 도입하면서 얻은 경험을 공유합니다. 이번 마이그레이션의 핵심은 Server Actions와 App Router 전환이었으며, 결과적으로 성능과 개발 생산성 모두에서 긍정적인 변화를 확인했습니다.
왜 Next.js 14로 업그레이드했나?
기존 Next.js 12 기반 프로젝트의 문제점:
- 클라이언트 번들 사이즈가 점점 비대해짐 (1.2MB+)
- API Routes 관리가 복잡해짐 (50개 이상의 엔드포인트)
- 초기 로딩 속도 저하 (LCP 3.5초)
- 코드 중복: 프론트엔드/백엔드 유효성 검사 로직
Server Actions의 핵심 장점
1. API Routes 불필요
기존에는 간단한 폼 처리도 API 엔드포인트가 필요했습니다:
[code=typescript]
// 기존 방식 (Pages Router + API Route)
// pages/api/contact = req.body;
await db);
res);
}
// pages/contact.tsx
const handleSubmit = async (e) => {
e.preventDefault();
await fetch(‘/api/contact’, {
method: ‘POST’,
body: JSON.stringify(formData)
});
};
[/code]
[code=typescript]
// Server Actions 방식 (App Router)
// app/contact/page);
revalidatePath(‘/contact’);
}
export default function ContactPage() {
return (
);
}
[/code]
결과: API Routes 50개 → 0개로 감소. 코드가 직관적이고 유지보수가 쉬워졌습니다.
2. End-to-End 타입 안정성
[code=typescript]
// actions/user.ts
‘use server’;
import { z } from ‘zod’;
const UserSchema = z);
export async function createUser(formData: FormData) {
const validated = UserSchema);
// validated의 타입이 자동으로 추론됨
return await db.user.create(validated);
}
[/code]
TypeScript와의 통합이 뛰어나, 런타임 에러를 줄이고 리팩토링 시에도 안전합니다.
3. Progressive Enhancement
Server Actions는 JavaScript 없이도 동작합니다:
[code=tsx]
{/* JS가 로드되지 않아도 폼 제출 가능 */}
{/* JS가 로드되면 자동으로 AJAX로 전환 */}
[/code]
Server Components 활용
데이터 페칭 간소화
[code=typescript]
// 기존: getServerSideProps
export async function getServerSideProps() {
const products = await fetchProducts();
return { props: { products } };
}
// App Router: 컴포넌트에서 직접 fetch
async function ProductList() {
const products = await fetchProducts(); // 서버에서 실행
return (
-
{products.map(p =>
- {p.name}
)}
);
}
[/code]
스트리밍과 Suspense
[code=tsx]
import { Suspense } from ‘react’;
export default function Dashboard() {
return (
대시보드
{/* 빠르게 로드되는 부분 */}
{/* 느린 데이터는 스트리밍 */}
<Suspense fallback={}>
<Suspense fallback={}>
);
}
[/code]
페이지 전체를 기다리지 않고 점진적으로 콘텐츠를 표시할 수 있습니다.
마이그레이션 과정
단계적 전환 전략
- 신규 페이지: App Router로 개발
- 공존 기간: pages/와 app/ 병행 운영
- 점진적 이전: 트래픽 낮은 페이지부터 전환
- 완전 전환: pages/ 폴더 제거
[code=js]
// next.config.js – 병행 운영 설정
module
};
[/code]
성과 측정
| 지표 | 이전 (Next 12) | 이후 (Next 14) | 개선 |
|---|---|---|---|
| 번들 사이즈 | 1.2 MB | 720 KB | -40% |
| LCP | 3.5초 | 1.8초 | -49% |
| TTFB | 800ms | 250ms | -69% |
| API 엔드포인트 | 50개 | 0개 | -100% |
| 빌드 시간 | 180초 | 95초 | -47% |
주의사항과 팁
- 클라이언트 컴포넌트 최소화: ‘use client’는 정말 필요한 곳에만
- 캐싱 전략 이해: fetch의 기본 캐싱 동작 숙지 필요
- 에러 바운더리: error.tsx로 에러 처리 구조화
- 로딩 상태: loading.tsx로 일관된 UX 제공
Next.js 14는 단순한 업그레이드가 아니라 웹 개발 방식의 패러다임 전환입니다. Server Actions와 Server Components를 적극 활용하면 더 빠르고, 더 단순하고, 더 안전한 애플리케이션을 만들 수 있습니다.