API Routes
Examples
Good to know : App Router를 사용하는 경우, API Routes 대신 Server Components 또는 Route Handlers 를 사용할 수 있습니다.
API routes는 Next.js로 공용 API 를 구축할 수 있는 솔루션을 제공합니다.
pages/api
폴더 내부의 모든 파일은 /api/*
로 매핑되어 page
대신 API 엔드포인트로 처리됩니다. 이러한 파일들은 서버 사이드 번들로만 존재하며, 클라이언트 사이드 번들 크기를 증가시키지 않습니다.
예를 들어, 다음 API 라우트는 상태 코드 200
과 함께 JSON 응답을 반환합니다:
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!' })
}
export default function handler(req, res) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
Good to know:
- API Routes는 기본적으로 동일 출처 만 허용하며, CORS 헤더를 지정하지 않습니다 (opens in a new tab) . 이러한 동작은 CORS 요청 도우미 (opens in a new tab) 로 요청 핸들러를 감싸서 사용자 정의할 수 있습니다.
- API Routes는 정적 내보내기 와 함께 사용할 수 없습니다. 그러나 App Router의 Route Handlers 를 사용할 수 있습니다.
- API Routes는
next.config.js
의 pageExtensions 설정 의 영향을 받습니다.
- API Routes는
Parameters
export default function handler(req: NextApiRequest, res: NextApiResponse) {
// ...
}
req
: http.IncomingMessage (opens in a new tab) 인스턴스res
: http.ServerResponse (opens in a new tab) 인스턴스
HTTP Methods
API 라우트에서 다양한 HTTP 메서드를 처리하려면 요청 핸들러에서 req.method
를 사용할 수 있습니다. 예:
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
// POST 요청 처리
} else {
// 다른 HTTP 메서드 처리
}
}
export default function handler(req, res) {
if (req.method === 'POST') {
// POST 요청 처리
} else {
// 다른 HTTP 메서드 처리
}
}
Request Helpers
API Routes는 들어오는 요청(req
)을 구문 분석하는 내장 요청 도우미를 제공합니다:
req.cookies
- 요청에 의해 전송된 쿠키를 포함하는 객체. 기본값은{}
req.query
- 쿼리 문자열 (opens in a new tab) 을 포함하는 객체. 기본값은{}
req.body
-content-type
에 따라 구문 분석된 body를 포함하는 객체, body가 전송되지 않은 경우null
Custom config
모든 API 라우트는 기본 설정을 변경하기 위해 config
객체를 내보낼 수 있습니다. 기본 설정은 다음과 같습니다:
export const config = {
api: {
bodyParser: {
sizeLimit: '1mb',
},
},
// 이 함수가 실행되는 최대 허용 시간을 지정함 (초 단위)
maxDuration: 5,
}
bodyParser
는 자동으로 활성화됩니다. body를 Stream
으로 소비하거나 raw-body (opens in a new tab) 로 소비하려면 이를 false
로 설정할 수 있습니다.
자동 bodyParsing
을 비활성화하는 한 가지 사용 사례는 예를 들어 GitHub (opens in a new tab) 웹훅 요청의 원본 body를 확인할 수 있도록 하는 것입니다.
export const config = {
api: {
bodyParser: false,
},
}
bodyParser.sizeLimit
은 bytes (opens in a new tab) 가 지원하는 형식으로 구문 분석된 body의 최대 크기입니다. 예를 들어:
export const config = {
api: {
bodyParser: {
sizeLimit: '500kb',
},
},
}
externalResolver
는 이 라우트가 express 또는 connect와 같은 외부 리졸버에 의해 처리되고 있음을 서버에 명시적으로 알리는 플래그입니다. 이 옵션을 활성화하면 해결되지 않은 요청에 대한 경고가 비활성화됩니다.
export const config = {
api: {
externalResolver: true,
},
}
responseLimit
는 자동으로 활성화되며, API 라우트의 응답 body가 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
서버 응답 객체 (opens in a new tab) (종종 res
로 약칭됨)에는 개발자 경험을 개선하고 새로운 API 엔드포인트를 생성하는 속도를 높이기 위한 Express.js와 유사한 도우미 메서드 세트가 포함되어 있습니다.
포함된 도우미는 다음과 같습니다:
res.status(code)
- 상태 코드를 설정하는 함수.code
는 유효한 HTTP 상태 코드 (opens in a new tab) 여야 합니다res.json(body)
- JSON 응답을 보냅니다.body
는 직렬화 가능한 객체 (opens in a new tab) 여야 합니다res.send(body)
- HTTP 응답을 보냅니다.body
는string
,object
또는Buffer
일 수 있음res.redirect([status,] path)
- 지정된 경로 또는 URL로 리디렉션합니다.status
는 유효한 HTTP 상태 코드 (opens in a new tab) 여야 하며, 지정되지 않으면 기본값은 "307" "임시 리디렉션"입니다.res.revalidate(urlPath)
-getStaticProps
를 사용하여 페이지를 필요에 따라 재검증 합니다.urlPath
는string
이어야 합니다.
Setting the status code of a response
클라이언트에 응답을 보낼 때 응답의 상태 코드를 설정할 수 있습니다.
다음 예제는 응답의 상태 코드를 200
(OK
)으로 설정하고 Hello from Next.js!
값의 message
프로퍼티와 함께 JSON 응답을 반환합니다:
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!' })
}
export default function handler(req, res) {
res.status(200).json({ message: 'Hello from Next.js!' })
}
Sending a JSON response
클라이언트에 응답을 보낼 때 JSON 응답을 보낼 수 있습니다. 이는 직렬화 가능한 객체 (opens in a new tab) 여야 합니다. 실제 애플리케이션에서는 요청된 엔드포인트의 결과에 따라 요청의 상태를 클라이언트에 알리고자 할 수 있습니다.
다음 예제는 상태 코드 200
(OK
)와 비동기 작업의 결과를 포함한 JSON 응답을 보냅니다. 오류가 발생할 수 있는 상황을 처리하기 위해 try catch 블록에 포함되어 있으며, 적절한 상태 코드와 함께 잡힌 오류 메시지를 클라이언트에 다시 보냅니다:
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: '데이터를 불러오는 데 실패했습니다.' })
}
}
export default async function handler(req, res) {
try {
const result = await someAsyncOperation()
res.status(200).json({ result })
} catch (err) {
res.status(500).json({ error: '데이터를 불러오는 데 실패했습니다.' })
}
}
Sending a HTTP response
HTTP 응답을 보내는 것은 JSON 응답을 보내는 것과 동일하게 작동합니다. 유일한 차이점은 응답 body가 string
, object
또는 Buffer
일 수 있다는 것입니다.
다음 예제는 상태 코드 200
(OK
)와 비동기 작업의 결과를 포함한 HTTP 응답을 보냅니다.
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: '데이터를 가져오는 데 실패했습니다' })
}
}
export default async function handler(req, res) {
try {
const result = await someAsyncOperation()
res.status(200).send({ result })
} catch (err) {
res.status(500).send({ error: '데이터를 가져오는 데 실패했습니다' })
}
}
Redirects to a specified path or URL
양식을 예로 들어, 양식을 제출한 후 클라이언트를 지정된 경로 또는 URL로 리디렉션하고자 할 수 있습니다.
다음 예제는 양식이 성공적으로 제출되면 클라이언트를 /
경로로 리디렉션합니다:
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: '데이터를 가져오는 데 실패했습니다' })
}
}
export default async function handler(req, res) {
const { name, message } = req.body
try {
await handleFormInputAsync({ name, message })
res.redirect(307, '/')
} catch (err) {
res.status(500).send({ error: '데이터를 가져오는 데 실패했습니다' })
}
}
Adding TypeScript types
NextApiRequest
및 NextApiResponse
타입을 next
에서 가져와 API Routes를 더 타입 안정적으로 만들 수 있습니다. 추가로, 응답 데이터도 타입 지정할 수 있습니다:
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!' })
}
Good to know :
NextApiRequest
의 body는any
입니다. 이는 클라이언트가 임의의 페이로드를 포함할 수 있기 때문입니다. body를 사용하기 전에 런타임에서 body의 타입/형태를 검증해야 합니다.
Dynamic API Routes
API Routes는 dynamic routes 를 지원하며, pages/
에 사용된 파일 명명 규칙을 따릅니다.
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const { pid } = req.query
res.end(`Post: ${pid}`)
}
export default function handler(req, res) {
const { pid } = req.query
res.end(`Post: ${pid}`)
}
이제 /api/post/abc
로의 요청은 Post: abc
라는 텍스트로 응답합니다.
Catch all API routes
API Routes는 괄호 안에 세 개의 점(...
)을 추가하여 모든 경로를 포착하도록 확장할 수 있습니다. 예:
pages/api/post/[...slug].js
는/api/post/a
와 일치하지만,/api/post/a/b
,/api/post/a/b/c
등과도 일치합니다.
Good to know :
slug
외에도[...param]
과 같은 이름을 사용할 수 있습니다.
일치하는 매개변수는 페이지에 쿼리 매개변수로 전송되며(예제에서는 slug
), 항상 배열 형태로 전송됩니다. 따라서 /api/post/a
경로는 다음과 같은 query
객체를 가집니다:
{ "slug": ["a"] }
그리고 /api/post/a/b
및 다른 일치하는 경로의 경우, 새로운 매개변수가 배열에 추가됩니다. 예:
{ "slug": ["a", "b"] }
예를 들어:
import type { NextApiRequest, NextApiResponse } from 'next'
export default function handler(req: NextApiRequest, res: NextApiResponse) {
const { slug } = req.query
res.end(`Post: ${slug.join(', ')}`)
}
export default function handler(req, res) {
const { slug } = req.query
res.end(`Post: ${slug.join(', ')}`)
}
이제 /api/post/a/b/c
로의 요청은 Post: a, b, c
라는 텍스트로 응답합니다.
Optional catch all API routes
모든 경로 포착 라우트를 선택적 포착 라우트로 만들려면 매개변수를 이중 괄호([[...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` (다중 요소 배열)
Caveats
- 미리 정의된 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
와는 일치하지 않습니다.
Edge API Routes
API Routes를 Edge Runtime과 함께 사용하고자 하는 경우, 점진적으로 App Router를 도입하고 Route Handlers 를 사용하는 것을 권장합니다.
Route Handlers 함수 시그니처는 isomorphic으로, Edge와 Node.js 런타임 모두에 동일한 함수를 사용할 수 있습니다.