Develop

Next.js Route Handlers 완벽 가이드 — App Router에서 API를 만드는 방법

Next.js App Router 아키텍처 환경에서 별도의 Express 서버 가동 없이 백엔드 REST API 엔드포인트를 구축할 수 있는 Route Handlers의 동작 사상과, Web API 표준 규격 하에서의 인증 가드 설계법을 실무 중심으로 해부합니다.

Next.jsRoute HandlersAPIApp Routerbackend
Next.js App Router의 route.ts 파일에서 GET, POST 핸들러가 정의된 코드 화면 — Route Handlers API 예시
  • ·Route Handlers는 app 디렉토리 안에 route.ts 파일로 생성하며 page.tsx와 같은 경로에 공존할 수 없다
  • ·GET, POST, PUT, DELETE, PATCH 등 HTTP 메서드 이름과 동일한 함수를 export하면 해당 메서드 요청을 처리한다
  • ·Route Handlers는 Edge Runtime과 Node.js Runtime 모두 지원하며 기본값은 Node.js Runtime이다
  • ·NextResponse.json()으로 JSON 응답을 반환하며 headers, cookies, status 코드를 함께 설정할 수 있다
기존 Pages Router 시절 pages/api/ 경로 밑에 (req, res) 형태의 Express 스타일 콜백 패턴에 길들여져 있다가, App Router의 route.ts로 전환했을 때 꽤나 진땀을 뺐습니다. NodeJS 전용이었던 요청 객체가 갑자기 브라우저 표준 명세인 Request 객체로 바뀌면서, req.body를 쳤다가 undefined 에러를 마주하거나, 쿼리 파라미터를 파싱하는 구조가 낯설어 헛발질을 꽤 했죠. 하지만 이 표준 Web API 명세에 완전히 적응하고 나니, Edge 런타임 분산 배포 환경에서도 엄청난 스피드로 API가 날아다니는 걸 체감하고 나서는 매우 감탄하며 신봉자가 되었습니다.

1. Web 표준 인터페이스 구조

Next.js Route Handlers 기반 App Router에서 웹 표준 API 엔드포인트 파싱하는 법

App Router의 API 규격을 설계하려면 특정 폴더 아래에 route.ts 파일을 생성해 배치합니다. 단, 해당 경로 폴더 안에 UI 렌더링용 page.tsx 파일이 있으면 빌드 에러가 나니 경로 분할에 신경 써야 합니다. 함수 명칭은 GET, POST, PUT, DELETE 등 HTTP 대문자 메서드명을 그대로 export하며, 입력 인자는 Request 표준 인터페이스를 따릅니다. 따라서 바디 정보를 파싱할 때는 await request.json() 비동기 읽기를 수행해야 하고, 쿼리스트링은 new URL(request.url).searchParams 객체를 개설해 직접 뽑아내야 하는 웹 표준 가이드를 철저히 수행해야 합니다.

// app/api/users/route.ts
import { NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const page = Number(searchParams.get('page') ?? '1');

  const users = await prisma.user.findMany({
    skip: (page - 1) * 20,
    take: 20,
  });
  return NextResponse.json(users);
}

export async function POST(request: Request) {
  const body = await request.json();
  const user = await prisma.user.create({ data: body });
  return NextResponse.json(user, { status: 201 });
}

2. JWT 인증 미들웨어 레이어

Next.js Route Handlers 전역 API 보안을 위한 JWT 인증 처리 노하우

로그인 상태를 판독해야 하는 핵심 비즈니스 API 영역은 Authorization 헤더 내의 Bearer JWT 토큰을 떼내어 서명을 검증하는 미들웨어 레이어가 장악해야 합니다. 이를 모든 개별 route.ts 마다 코드 복사 붙여넣기로 때우다간 유지 보수가 지옥이 됩니다. 해결책은 Route Handler를 감싸는 고차 함수(Higher-Order Function) 패턴의 withAuth 유틸리티를 개설하여 검증 단계를 통제하는 것입니다. 혹은 프로젝트 최상단의 middleware.ts 내부에서 특정 /api/* 하위 경로를 매칭 타겟으로 잡아 토큰 가드를 일괄 인젝션해주면, 개별 API 코드에는 오직 핵심 데이터 처리 비즈니스만 담겨 가독성이 기가 막히게 올라갑니다.

3. 동적 파라미터와 캐시 통제

Next.js Route Handlers에서 동적 경로 파라미터 매핑 및 force-dynamic 캐시 제어 요령

/api/posts/[id] 형태의 상세 타겟 API를 잡으려면 대괄호 폴더명 전략을 취합니다. 핸들러 함수의 두 번째 인자인 context 속성 내부의 params 비동기 객체를 수령하여 (await params).id 형태로 타겟 ID 값을 안전하게 획득할 수 있죠. 여기서 가장 빈번히 터지는 장애는 GET 메서드 핸들러가 빌드 타임에 단순 static 파일처럼 정적으로 박제되어 실시간 데이터베이스의 변경점을 반영하지 못하고 엣지 캐시만 무한 서빙하는 끔찍한 현상입니다. 실시간 동적 조회가 필수인 API 파일 상단에는 반드시 export const dynamic = 'force-dynamic' 설정을 고정 기입해 주는 습관을 들여야 합니다.

자주 묻는 질문

Route Handler 내부에서 쿠키를 생성하거나 삭제하여 클라이언트에 반영할 수 있나요?+

네, 가능합니다. next/headers에서 cookies 유틸 훅을 불러와 cookies().set('name', 'value') 혹은 cookies().delete('name') 구문을 기재해 주면, NextJS 가 알아서 HTTP 응답 헤더의 Set-Cookie 필드를 설정해 안전한 쿠키 통신을 마감해 줍니다.

Server Actions 기술이 나왔는데 굳이 Route Handlers API를 써야 하는 명확한 기준이 뭔가요?+

내부 리액트 컴포넌트 폼 제출 처리라면 연동 구조가 심플한 Server Actions가 압도적으로 효율적입니다. 하지만 우리 서비스와 연계된 스마트폰 모바일 앱(iOS, Android)이나 외부 협력업체 서버가 내 API를 가져다 HTTP 호출을 해야 하는 오픈 API 규격의 개발 도메인이라면 무조건 규격화된 Route Handlers를 제공해 주는 것이 정석적인 분할 전술입니다.

관련 글