라우팅: API Routes
라우팅: API Routes | Next.js
섹션 제목: “라우팅: API Routes | Next.js”Source URL: https://nextjs.org/docs/pages/building-your-application/routing/api-routes
API Routes
섹션 제목: “API Routes”최종 업데이트 2026년 2월 20일
예시
알아두면 좋아요 : App Router를 사용하는 경우 API Routes 대신 Server Components 또는 Route Handlers를 사용할 수 있습니다.
API Routes는 Next.js로 공개 API 를 구축할 수 있는 솔루션을 제공합니다.
pages/api 폴더 내부의 모든 파일은 /api/* 로 매핑되며 page 가 아닌 API 엔드포인트로 처리됩니다. 이들은 서버 전용 번들이므로 클라이언트 번들 크기를 증가시키지 않습니다.
예를 들어 다음 API Route는 상태 코드 200 인 JSON 응답을 반환합니다:
pages/api/hello.ts
JavaScriptTypeScript
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = { message: string }
export default function handler( req: NextApiRequest, res: NextApiResponse<ResponseData> ) { res.status(200).json({ message: 'Hello from Next.js!' }) }알아두면 좋아요 :
- API Routes는 기본적으로 CORS 헤더를 지정하지 않습니다. 즉 기본값으로 동일 출처만 허용합니다. CORS 요청 도우미로 요청 핸들러를 감싸 이 동작을 사용자 지정할 수 있습니다.
- API Routes는 정적 내보내기와 함께 사용할 수 없습니다. 단, App Router의 Route Handlers는 가능합니다.
- API Routes는
next.config.js의pageExtensions구성의 영향을 받습니다.
Parameters
섹션 제목: “Parameters” export default function handler(req: NextApiRequest, res: NextApiResponse) { // ... }req: http.IncomingMessage의 인스턴스res: http.ServerResponse의 인스턴스
HTTP Methods
섹션 제목: “HTTP Methods”API Route에서 다양한 HTTP 메서드를 처리하려면 요청 핸들러에서 req.method 를 사용할 수 있습니다:
pages/api/hello.ts
JavaScriptTypeScript
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) { if (req.method === 'POST') { // Process a POST request } else { // Handle any other HTTP method } }Request Helpers
섹션 제목: “Request Helpers”API Routes는 들어오는 요청(req)을 파싱하는 기본 제공 요청 도우미를 제공합니다:
req.cookies- 요청이 보낸 쿠키를 포함한 객체입니다. 기본값은{}req.query- 쿼리 문자열을 포함한 객체입니다. 기본값은{}req.body-content-type으로 파싱된 body를 포함한 객체이며, body가 없으면null입니다
Custom config
섹션 제목: “Custom config”모든 API Route는 다음과 같은 기본 구성을 변경하기 위해 config 객체를 내보낼 수 있습니다:
export const config = { api: { bodyParser: { sizeLimit: '1mb', }, }, // Specifies the maximum allowed duration for this function to execute (in seconds) maxDuration: 5, }bodyParser 는 자동으로 활성화됩니다. body를 Stream 또는 raw-body로 소비하려면 이를 false 로 설정하세요.
자동 bodyParsing 을 비활성화하는 한 가지 사용 사례는 예를 들어 GitHub와 같은 웹훅 요청의 원시 body를 검증하는 것입니다.
export const config = { api: { bodyParser: false, }, }bodyParser.sizeLimit 는 bytes가 지원하는 형식이라면 어떤 것이든 사용할 수 있으며, 파싱된 body의 최대 크기입니다:
export const config = { api: { bodyParser: { sizeLimit: '500kb', }, }, }externalResolver 는 이 라우트가 express 또는 connect 와 같은 외부 리졸버에 의해 처리되고 있음을 서버에 명시적으로 알리는 플래그입니다. 이 옵션을 활성화하면 해결되지 않은 요청에 대한 경고가 비활성화됩니다.
export const config = { api: { externalResolver: true, }, }responseLimit 는 기본적으로 활성화되어 있으며 API Routes의 응답 본문이 4MB를 초과하면 경고합니다.
서버리스 환경이 아닌 곳에서 Next.js를 사용하고 CDN 또는 전용 미디어 호스트를 사용하지 않을 때의 성능 영향을 이해한다면, 이 제한을 false 로 설정할 수 있습니다.
export const config = { api: { responseLimit: false, }, }responseLimit 은 바이트 수나 bytes 가 지원하는 문자열 형식(1000, '500kb', '3mb' 등)을 받을 수도 있습니다. 이 값은 경고가 표시되기 전의 최대 응답 크기입니다. 기본값은 4MB입니다(위 참조).
export const config = { api: { responseLimit: '8mb', }, }Response Helpers
섹션 제목: “Response Helpers”Server Response 객체(종종 res 로 줄여 씀)에는 Express.js와 유사한 도우미 메서드가 포함되어 있어 개발자 경험을 개선하고 새로운 API 엔드포인트를 더 빠르게 만들 수 있습니다.
포함된 도우미는 다음과 같습니다:
res.status(code)- 상태 코드를 설정하는 함수입니다.code는 유효한 HTTP 상태 코드여야 합니다.res.json(body)- JSON 응답을 전송합니다.body는 직렬화 가능한 객체여야 합니다.res.send(body)- HTTP 응답을 전송합니다.body는string,object,Buffer가 될 수 있습니다.res.redirect([status,] path)- 지정된 경로나 URL로 리디렉션합니다.status는 유효한 HTTP 상태 코드여야 합니다. 지정하지 않으면status는 “307” “Temporary redirect”로 기본 설정됩니다.res.revalidate(urlPath)-getStaticProps를 사용하여 수요 기반으로 페이지를 재검증합니다.urlPath는string이어야 합니다.
응답의 상태 코드 설정
섹션 제목: “응답의 상태 코드 설정”클라이언트에 응답을 보낼 때 응답의 상태 코드를 설정할 수 있습니다.
다음 예시는 응답의 상태 코드를 200 (OK)으로 설정하고 JSON 응답으로 Hello from Next.js! 값을 가진 message 속성을 반환합니다:
pages/api/hello.ts
JavaScriptTypeScript
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = { message: string }
export default function handler( req: NextApiRequest, res: NextApiResponse<ResponseData> ) { res.status(200).json({ message: 'Hello from Next.js!' }) }JSON 응답 보내기
섹션 제목: “JSON 응답 보내기”클라이언트로 응답을 보낼 때 JSON 응답을 보낼 수 있으며, 이 객체는 직렬화 가능해야 합니다. 실제 애플리케이션에서는 요청된 엔드포인트 결과에 따라 클라이언트에 요청 상태를 알리고 싶을 수 있습니다.
다음 예시는 상태 코드 200 (OK)과 비동기 작업 결과로 JSON 응답을 보냅니다. 발생할 수 있는 오류를 처리하기 위해 try-catch 블록에 포함되어 있으며, 적절한 상태 코드와 오류 메시지를 포착해 클라이언트에 다시 보냅니다:
pages/api/hello.ts
JavaScriptTypeScript
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler( req: NextApiRequest, res: NextApiResponse ) { try { const result = await someAsyncOperation() res.status(200).json({ result }) } catch (err) { res.status(500).json({ error: 'failed to load data' }) } }HTTP 응답 보내기
섹션 제목: “HTTP 응답 보내기”HTTP 응답을 보내는 방법은 JSON 응답을 보낼 때와 동일합니다. 유일한 차이는 응답 본문이 string, object, Buffer 가 될 수 있다는 점입니다.
다음 예시는 상태 코드 200 (OK)와 비동기 작업 결과로 HTTP 응답을 보냅니다.
pages/api/hello.ts
JavaScriptTypeScript
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler( req: NextApiRequest, res: NextApiResponse ) { try { const result = await someAsyncOperation() res.status(200).send({ result }) } catch (err) { res.status(500).send({ error: 'failed to fetch data' }) } }지정된 경로나 URL로 리디렉션
섹션 제목: “지정된 경로나 URL로 리디렉션”양식을 예로 들면, 사용자가 양식을 제출한 후 클라이언트를 지정된 경로나 URL로 리디렉션하고 싶을 수 있습니다.
다음 예시는 양식이 성공적으로 제출되면 클라이언트를 / 경로로 리디렉션합니다:
pages/api/hello.ts
JavaScriptTypeScript
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler( req: NextApiRequest, res: NextApiResponse ) { const { name, message } = req.body
try { await handleFormInputAsync({ name, message }) res.redirect(307, '/') } catch (err) { res.status(500).send({ error: 'Failed to fetch data' }) } }TypeScript 타입 추가하기
섹션 제목: “TypeScript 타입 추가하기”API Routes를 더 타입 안전하게 만들려면 next 에서 NextApiRequest 및 NextApiResponse 타입을 가져올 수 있으며, 여기에 응답 데이터 타입도 지정할 수 있습니다:
import type { NextApiRequest, NextApiResponse } from 'next'
type ResponseData = { message: string }
export default function handler( req: NextApiRequest, res: NextApiResponse<ResponseData> ) { res.status(200).json({ message: 'Hello from Next.js!' }) }알아두면 좋아요 :
NextApiRequest의 본문은 클라이언트가 어떤 페이로드든 보낼 수 있기 때문에any입니다. 사용하기 전에 반드시 런타임에서 본문의 타입과 구조를 검증하세요.
동적 API 라우트
섹션 제목: “동적 API 라우트”API 라우트는 동적 라우트를 지원하며, pages/에 사용하는 것과 동일한 파일 명명 규칙을 따릅니다.
pages/api/post/[pid].ts
JavaScriptTypeScript
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) { const { pid } = req.query res.end(`Post: ${pid}`) }이제 /api/post/abc 요청은 Post: abc라는 텍스트로 응답합니다.
캣치올 API 라우트
섹션 제목: “캣치올 API 라우트”API 라우트는 대괄호 안에 점 세 개(...)를 추가하여 모든 경로를 포착하도록 확장할 수 있습니다. 예를 들어:
pages/api/post/[...slug].js는/api/post/a뿐 아니라/api/post/a/b,/api/post/a/b/c등에도 매칭됩니다.
알아두면 좋아요 :
slug대신[...param]처럼 다른 이름을 사용할 수 있습니다.
매칭된 파라미터는 페이지로 쿼리 파라미터(예시에서는 slug)로 전달되며, 항상 배열 형태입니다. 따라서 /api/post/a 경로는 다음과 같은 query 객체를 갖습니다:
{ "slug": ["a"] }/api/post/a/b와 동일하게 매칭되는 다른 경로의 경우, 새로운 파라미터가 배열에 추가됩니다:
{ "slug": ["a", "b"] }예시:
pages/api/post/[…slug].ts
JavaScriptTypeScript
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) { const { slug } = req.query res.end(`Post: ${slug.join(', ')}`) }이제 /api/post/a/b/c 요청은 Post: a, b, c라는 텍스트로 응답합니다.
선택적 캣치올 API 라우트
섹션 제목: “선택적 캣치올 API 라우트”캣치올 라우트는 파라미터를 이중 대괄호([[...slug]])로 감싸 선택적으로 만들 수 있습니다.
예를 들어 pages/api/post/[[...slug]].js는 /api/post, /api/post/a, /api/post/a/b 등과 매칭됩니다.
캣치올과 선택적 캣치올 라우트의 주요 차이는 선택적 라우트에서는 파라미터 없이도 경로가 매칭된다는 점입니다(위 예시의 /api/post).
query 객체는 다음과 같습니다:
{ } // GET `/api/post` (빈 객체) { "slug": ["a"] } // `GET /api/post/a` (단일 요소 배열) { "slug": ["a", "b"] } // `GET /api/post/a/b` (다중 요소 배열)주의 사항
섹션 제목: “주의 사항”- 사전에 정의된 API 라우트가 동적 API 라우트보다 우선하며, 동적 API 라우트는 캣치올 API 라우트보다 우선합니다. 다음 예시를 참고하세요:
pages/api/post/create.js-/api/post/create와 매칭pages/api/post/[pid].js-/api/post/1,/api/post/abc등과 매칭하지만/api/post/create와는 매칭되지 않음pages/api/post/[...slug].js-/api/post/1/2,/api/post/a/b/c등과 매칭하지만/api/post/create,/api/post/abc와는 매칭되지 않음
스트리밍 응답
섹션 제목: “스트리밍 응답”Pages Router는 API 라우트에서 스트리밍 응답을 지원하지만, Next.js 14 이상이라면 App Router를 점차 채택하고 Route Handlers를 사용할 것을 권장합니다.
다음은 writeHead를 사용해 API 라우트에서 응답을 스트리밍하는 방법입니다:
pages/api/hello.ts
JavaScriptTypeScript
import { NextApiRequest, NextApiResponse } from 'next'
export default async function handler( req: NextApiRequest, res: NextApiResponse ) { res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-store', }) let i = 0 while (i < 10) { res.write(`data: ${i}\n\n`) i++ await new Promise((resolve) => setTimeout(resolve, 1000)) } res.end() }보내기