Next.js 13+ App Router가 도입되면서, 기존 pages/api 방식 대신 Route Handler라는 새로운 서버 API 작성 방식이 등장했습니다
Route Handler
- Route Handler는 app/api/**/route.ts 파일 안에서 GET, POST, DELETE, PUT 등 HTTP 메서드를 함수로 export하여 API를 만드는 방식입니다.
- Next.js 서버가 이 파일을 읽고, 각 메서드를 API endpoint로 자동 매핑해줍니다.
기존 방식과 비교
| 방식 | 파일 위치 | 특징 |
| pages API | pages/api/* | Next.js 12 스타일, 페이지 라우터에 의존 |
| Route Handler | app/api/*/route.ts | App Router 기반, 서버 컴포넌트 친화적, 최신 공식 방식 |
Route Handler가 왜 필요한가?
1) App Router와 완전 통합
- 서버 컴포넌트와 자연스럽게 연동됨
- fetch 시 자동 캐싱/리밸리데이션 기능 활용 가능
- 서버 액션과 조합 가능
2) 파일 기반 API
- 파일 생성만으로 API 라우트 자동 생성
- API URL = 폴더 구조 그대로
3) Edge Runtime 지원
- 글로벌 초고속 API 구성 가능
예제: /api/tasks CRUD
- GET: 전체 tasks 조회
- POST: 새로운 task 생성
- DELETE: 특정 task 삭제
폴더 구조
app/
api/
tasks/
route.ts
tasks/
page.tsx
/api/tasks/route.ts 구현
타입 정의
interface Task {
id: number;
title: string;
completed: boolean;
}
interface CreateTaskRequest {
title: string;
}
임시 데이터
let tasks: Task[] = [
{ id: 1, title: "Learn Next.js", completed: false },
{ id: 2, title: "Build a project", completed: false },
];
GET — 전체 조회
export async function GET() {
return Response.json(tasks);
}
POST — 새로운 task 생성
export async function POST(req: Request) {
const body: CreateTaskRequest = await req.json();
if (!body.title) {
return new Response("Title is required", { status: 400 });
}
const newTask = {
id: tasks.length + 1,
title: body.title,
completed: false,
};
tasks.push(newTask);
return new Response(JSON.stringify(newTask), { status: 201 });
}
DELETE — task 삭제
export async function DELETE(req: Request) {
const { searchParams } = new URL(req.url);
const id = Number(searchParams.get("id"));
if (!id) {
return new Response("ID is required", { status: 400 });
}
const index = tasks.findIndex((t) => t.id === id);
if (index === -1) {
return new Response("Task not found", { status: 404 });
}
tasks.splice(index, 1);
return new Response("Task deleted", { status: 200 });
}
API를 사용하는 페이지 /tasks/page.tsx
export default async function TasksPage() {
const res = await fetch("http://localhost:3000/api/tasks", {
cache: "no-store",
});
const tasks = await res.json();
return (
<div>
<h1>Tasks</h1>
<pre>{JSON.stringify(tasks, null, 2)}</pre>
</div>
);
}
cache: "no-store"?
- Route Handler는 기본적으로 fetch 결과가 캐싱됩니다.
- SSR에서 최신 데이터를 원한다면 반드시 no-store가 필요합니다.
'개발 공부 > React' 카테고리의 다른 글
| UploadThing을 통한 이미지 업로드 구현하기 (0) | 2025.11.27 |
|---|---|
| Next.js App Router 자동 실행 규칙 (0) | 2025.11.24 |
| Clerk 인증 정보와 Prisma User 테이블 동기화(sync) (0) | 2025.11.06 |
| useSearchParams hook 만들기 (1) | 2025.10.22 |
| custom modal 만들기 (0) | 2025.10.21 |