🌼 해당 글은 다음 스펙을 기준으로 작성되었습니다.
NextJS 공식 문서(pages router) - API Routes
들어가기에 앞서, 공식문서에도 나와있듯이 만약 App Router를 사용한다면 API Routes 대신 Server Components나 Route Handlers를 사용할 수 있다. 해당 포스팅은 pages router에서의 API Routes 공식 문서를 바탕으로 작성할 예정이다.
API Routes란 쉽게 말하면 NextJS에서 제공하는 NextJS 앱 내에서 API를 만들 수 있게 해주는 기능이다. pages/api
폴더 내의 모든 파일은 /api/*
에 대응되며, page
가 아닌 API 엔드포인트로 취급된다. 이는 서버 사이드 번들이며, 클라이언트 사이드 번들 크기를 증가시키지 않는다.
pages/api/hello.ts
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 라우트 pages/api/hello.ts
는 상태코드 200
을 가진 json
응답을 반환한다. API 라우트가 동작하려면 다음과 같은 매개변수를 받는 함수를 default
로 내보내야 한다. (일명 요청 핸들러)
req
: http.IncomingMessage 인스턴스res
: http.ServerResponse 인스턴스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 메서드 처리
}
}
API 라우트는 들어오는 요청(req)을 파싱하는 내장 요청 헬퍼를 제공한다.
req.cookies
- 요청에 따라 전송된 쿠키를 포함하는 객체. 기본 값은 {}
req.query
- 쿼리 문자열을 포함하는 객체. 기본 값은 {}
req.body
- content-type
에 따라 분석된 body를 포함하는 객체, 또는 body가 전송되지 않은 경우 null
res
(서버 응답 객체)는 DX를 향상하고 새로운 API 엔드포인트를 빠르게 생성하는 데 도움을 주기 위해 Express.js
와 유사한 여러 헬퍼 함수를 포함하고 있다.
res.status(code)
- 상태 코드를 설정하는 함수. code
는 유효한 HTTP 상태 코드여야 한다.res.json(body)
- JSON 응답을 보낸다. body
는 직렬화할 수 있는 객체여야 한다.res.redirect([status,] path)
- 지정된 경로 또는 URL로 리다이렉트한다. status
는 유효한 HTTP 상태 코드여야 한다. 지정하지 않는다면 status
의 기본 값은 "307", 즉 "임시 다이렉트(Temporary redirect)"이다.res.revalidate(urlPath)
- getStaticProps
를 사용하여 요청 시 페이지 재검증을 수행한다. urlPath
는 string
이어야 한다.응답을 클라이언트에게 보낼 때, 응답 상태 코드를 설정할 수 있다. 다음 예시는 응답의 상태코드를 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!' })
}
예를 들어 form을 사용할 경우, 클라이언트가 form을 제출하면 지정된 경로 또는 URL로 리다이렉트할 수 있다.
다음 예시는 form을 성공적으로 제출하면 클라이언트를 /
로 리다이렉트하는 코드이다.
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' })
}
}
API 라우트는 동적 라우트를 지원하며 pages
에 사용되는 파일 이름 규칙을 따른다. 예를 들어 API 라우트 pages/api/post/[pid].js
에 다음 코드가 있다.
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
를 응답으로 받게 된다.
나는 프로젝트에서 JWT를 HttpOnly 쿠키에 전달하기 위해 API Routes를 사용했었다. (참고)
쿠키에 있는 JWT의 여부를 가지고 로그인 상태를 확인했기 때문에 사용자가 로그아웃을 선택하면 쿠키에 있는 JWT를 제거해야 했다. 그 때 사용한 로그아웃 API 라우트는 다음과 같다.
/pages/api/auth/logout.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { deleteCookie } from 'cookies-next';
export default function logout(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
deleteCookie('accessToken', { req, res, path: '/' });
deleteCookie('refreshToken', { req, res, path: '/' });
res.status(200).json({ message: '로그아웃 성공 | 토큰 삭제' });
} else {
res.setHeader('Allow', ['POST']);
res.status(405).end(`Method ${req.method} Not Allowed`);
}
POST 요청일 때만 실행되도록 하였고, 만약 POST가 아닌 다른 HTTP Method 요청이 들어왔다면 405
상태코드와 Method ${req.method} Not Allowed
를 응답으로 보냈다.
logout API 라우트로 POST 요청이 왔을 때 쿠키에 있는 accessToken
과 refreshToken
을 제거하였고, 상태코드 200
을 가진 json을 응답으로 반환하였다.
다음은 해당 logout API 라우트에 요청을 보내는 코드이다.
const handleLogout = () => {
logoutApi()
.then(() => {
axios
.post(
'/api/auth/logout',
{},
{
headers: {
'Content-Type': 'application/json',
},
},
)
.then(() => {
router
.push({
pathname: '/',
query: { logout: true },
})
})
};
로그아웃 버튼 클릭 시 handleLogout
이 실행되도록 하였다. 가장 먼저 백엔드 서버에 로그아웃 요청(logoutApi()
)을 보내고, 백엔드 서버 로그아웃이 성공적으로 응답이 오면 내가 만든 logout API 라우트로 post 요청을 보내 쿠키에 있는 JWT를 제거하였다. 쿠키 제거까지 완료되면 /
로 쿼리와 함께 리다이렉션하도록 처리하였다.