서버리스 함수 활용
Next.js App Router 환경에서 서버리스 함수를 활용하는 것은 확장성 있고 효율적인 백엔드 로직을 구현하는 강력한 방법입니다.
이 절에서는 서버리스 함수의 개념, 장점, 그리고 Next.js 애플리케이션에서의 구현 방법에 대해 알아보겠습니다.
서버리스 아키텍처의 장점
- 자동 확장성
- 비용 효율성 (사용한 만큼만 지불)
- 인프라 관리 부담 감소
- 빠른 배포 및 업데이트
API 라우트를 서버리스 함수로 배포
Next.js App Router에서 API 라우트는 app/api
디렉토리 내에 route.js
파일로 정의됩니다.
이 파일들은 Vercel이나 다른 서버리스 플랫폼에 배포될 때 자동으로 서버리스 함수로 변환됩니다.
예시
import { NextResponse } from 'next/server';
export async function GET(request) {
return NextResponse.json({ message: 'Hello, Serverless World!' });
}
이 API 라우트는 배포 시 자동으로 서버리스 함수로 변환됩니다.
환경 변수 관리
서버리스 환경에서 환경 변수를 관리하는 방법
.env.local
파일 사용 (개발 환경)- Vercel 대시보드에서 환경 변수 설정 (프로덕션 환경)
import { NextResponse } from 'next/server';
import { connectToDatabase } from '@/lib/db';
export async function GET() {
const db = await connectToDatabase(process.env.MONGODB_URI);
// 데이터베이스 연산 수행
return NextResponse.json({ success: true });
}
콜드 스타트 최소화 전략
- 함수 크기 최소화 : 필요한 의존성만 포함
- 연결 풀링 : 데이터베이스 연결 재사용
- 함수 미리 워밍업 : 정기적으로 함수 호출
예시
import { MongoClient } from 'mongodb';
let cachedClient = null;
export async function connectToDatabase() {
if (cachedClient) {
return cachedClient;
}
const client = await MongoClient.connect(process.env.MONGODB_URI);
cachedClient = client;
return client;
}
서버리스 함수와 데이터베이스 연동
서버리스 함수에서 데이터베이스 연결 예시
import { NextResponse } from 'next/server';
import { connectToDatabase } from '@/lib/db';
export async function GET() {
const client = await connectToDatabase();
const db = client.db('my-database');
const users = await db.collection('users').find().toArray();
return NextResponse.json(users);
}
export async function POST(request) {
const client = await connectToDatabase();
const db = client.db('my-database');
const { name, email } = await request.json();
const result = await db.collection('users').insertOne({ name, email });
return NextResponse.json(result);
}
Vercel과 AWS Lambda 비교
1. Vercel
- Next.js에 최적화
- 간편한 배포 프로세스
- 자동 HTTPS, CDN 설정
2. AWS Lambda
- 더 많은 커스터마이징 옵션
- 다양한 AWS 서비스와의 통합
- 복잡한 설정 필요
11장 API 라우트와의 연관성
16장의 서버리스 함수 활용은 11장에서 다룬 API 라우트와 직접적으로 연관됩니다.
App Router의 API 라우트 (app/api
디렉토리의 route.js
파일들)는 서버리스 환경에 배포될 때 자동으로 개별 서버리스 함수로 변환됩니다.
이를 통해 11장에서 구현한 API 로직을 그대로 서버리스 아키텍처에서 활용할 수 있습니다.
실습 : 이메일 전송 서버리스 함수
이메일 전송 기능을 수행하는 서버리스 함수를 구현하고 Next.js 애플리케이션과 통합해보겠습니다.
- 필요한 패키지 설치
npm install nodemailer
- 이메일 전송 API 라우트 구현
import { NextResponse } from 'next/server';
import nodemailer from 'nodemailer';
export async function POST(request) {
const { to, subject, text } = await request.json();
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
});
try {
await transporter.sendMail({
from: process.env.FROM_EMAIL,
to,
subject,
text,
});
return NextResponse.json({ success: true });
} catch (error) {
console.error('Email send error:', error);
return NextResponse.json({ error: 'Failed to send email' }, { status: 500 });
}
}
- 클라이언트 측 컴포넌트에서 이메일 전송 함수 호출
'use client'
import { useState } from 'react';
export default function EmailForm() {
const [email, setEmail] = useState('');
const [subject, setSubject] = useState('');
const [message, setMessage] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
try {
const response = await fetch('/api/send-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ to: email, subject, text: message }),
});
const data = await response.json();
if (data.success) {
alert('Email sent successfully!');
} else {
throw new Error(data.error);
}
} catch (error) {
alert('Failed to send email: ' + error.message);
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Recipient Email"
required
/>
<input
type="text"
value={subject}
onChange={(e) => setSubject(e.target.value)}
placeholder="Subject"
required
/>
<textarea
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="Message"
required
/>
<button type="submit">Send Email</button>
</form>
);
}
- 환경 변수 설정 (
.env.local
및 Vercel 대시보드)
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=your-username
SMTP_PASS=your-password
[email protected]
- 이메일 폼 컴포넌트를 페이지에 추가
import EmailForm from './components/EmailForm';
export default function Home() {
return (
<main>
<h1>Send Email</h1>
<EmailForm />
</main>
);
}
이 실습을 통해 서버리스 함수를 사용하여 이메일 전송 기능을 구현하고, Next.js App Router 애플리케이션과 통합하는 과정을 경험할 수 있습니다.
실습의 경우처럼 Next.js에서는 서버리스 함수를 활용하는 것으로 확장성 있고 유지보수가 쉬운 백엔드 로직을 구현할 수 있습니다.
이로써 풀스택 프레임워크인 Next.js에서는 API 라우트 기능과 결합하여 프론트엔드와 백엔드를 긴밀하게 통합해볼 수 있었습니다.