API Routes

landvide·2021년 8월 10일
2

1. API 라우트 생성하기

Next.js에서는 Node.js Serverless function으로 api endpoint를 쉽게 만들 수 있다.
/pages/api 디렉토리에 함수 하나만 만들면 된다.

옵션에 따라 Serverless 가능

page/api/user.js 는 상태코드 200과 함께 json 형식의 응답을 한다.

export default function handler(req, res) {
  res.status(200).json({ name: 'John Doe' })
}

확인해보자.

다른 HTTP method(POST, GET, DELETE 등)를 처리하기 위해 'req.method'를 사용할 수 있다.

예시)

export default function handler (req, res) => {
	 if (req.method === 'POST') {
    // POST request 처리
  } else {
    // 다른 HTTP method 처리
  }
}

ㆍreq : 요청 데이터
ㆍres : 응답 데이터

Dynamic API Routes

API Routes도 dynamic routes를 제공해준다.

예를 들어, pages/api/post/[pid].js 파일이 다음과 같다고 하자.

export default function handler(req, res) {
  const { pid } = req.query
  res.end(`Post: ${pid}`)
}

/api/post/abc를 호출하면 'Post: abc'가 나타날 것이다.
동적 경로 라우팅과 같다.

RESTful API 만들기

RESTful api 패턴은 대표적으로 아래와 같다.

RESTful api가 무엇인지는 여기 를 참고하자.

ㆍGET api/posts -블로그 글들의 리스트를 불러온다.
ㆍGET api/posts/12345 - 글 아이디(예시)가 12345인 글의 api 결과를 불러온다.

두가지 방법으로 구현할 수 있는데,

-Option 1:
/api/posts.js
/api/posts/[postId].js

-Option 2:
/api/posts/index.js
/api/posts/[postId].js

두 개는 동일하다. 두 방법 모두 리스트가 반환될 지, 글 한 개가 반환될 지 코드를 구분해서 사용할 수 있기 때문에 추후에 Serverless 형태로 가기 좋은 구조이다.
실제로 서버 구현할 때 많이 사용되는 방법이다.

/api/posts/[postId].js 만 사용하는 세번 째 옵션은 유효하지 않다.
Dynamic Routes(Catch-all routes를 포함하는)가 'undefined' 상태를 가지지 않기 때문에! 그래서 /api/posts/api/posts/[postId].js 와 매치되지 않을 것이다.

Catch all API routes

하위 경로를 전부 포함하기

위에서 api/post/12345 가 url 하나에만 매칭되었다면, api/post/12345/a, api/post/12345/a/b 와 같이 여러 depth에 걸친 url을 함께 다루기도 가능하다.

방법은 파일명의 대괄호 안에 점 3개(...)를 추가하여 모든 경로가 잡히도록 확장시키는 것!

예시)

pages/api/post/[...slug].js/api/post/a 와 매치된다. 또한, /api/post/a/b/api/post/a/b/c 등에도 전부 매칭이 이루어진다.

만약 api/post/a url이 매칭되면 req객체의 query는 다음과 같다.

{ "slug": ["a"] }

url이 api/post/a/b/c인 경우,

{ "slug": ["a","b","c"] }

예시)

export default function handler(req, res) {
  const { slug } = req.query
  res.end(`Post: ${slug.join(', ')}`)
}

리턴 값은 "Post: a,b,c"가 된다.

상위경로 포함하기

추천하는 방법은 아니지만, api/postapi/post/a 두 개의 경로를 한 번에 다룰수 있기는 하다.
방법은 파일명에 대괄호 두 번 사용하기!

pages/api/post/[[...slug]]

query 값은 아래와 같이 나올 것이다.

{} // api/post
{ "slug": ["a"] } // api/post/a
{ "slug" : ["a","b"] } //api/post/a/b

우선순위

사전 정의된 api 라우트 > 동적 api 라우트 > catch all api 라우트

API Middlewares

req를 해석하는 built-in된 미들웨어

ㆍreq.cookies : 요청에 쿠키가 보내졌는지 담는 객체. 기본 {}
ㆍreq.query : 쿼리스트링을 포함하는 객체. 기본 {}
ㆍreq.body : content-Type 별로 해석된 body를 담는 객체, body에 아무것도 없으면 null

모든 api 경로는 config 객체를 사용하여 기본 설정을 변경할 수 있다.

export const config = {
  api: {
    bodyParser: {
      sizeLimit: '1mb',
    },
  },
}

sizeLimit은 해석된 body에 담길 최대 크기이다. (byte 단위)

bodyParser는 body parsing을 활성화, Stream으로 처리하고 싶으면 비활성화

export const config = {
  api: {
    bodyParser: false,
  },
}

아래의 externalResolver 속성은 경로가 외부 확인자(express or connect)에 의해 처리되고 있음을 서버에 알리는 플래그이다.
해당 옵션을 사용하면 확인되지 않은 요청에 대한 경고가 비활성화 된다.

export const config = {
  api: {
    externalResolver: true,
  },
}

Connect/Express middleware

적합한 middleware를 connect 연결할 수 있다.
예로, api endpoint를 위해서 CORS 설정이 필요한 경우에 cors 패키지를 활용하여 수행할 수 있다.

cors란? Cross-Origin Resource Sharing(CORS)은 추가적인 HTTP header를 사용해서 애플리케이션이 다른 origin의 리소스에 접근할 수 있도록 하는 메커니즘을 말한다. 하지만 다른 origin에서 내 리소스에 함부로 접근하지 못하게 하기 위해 사용된다.

cors를 설치하자.

npm i cors
or
yarn add cors

그 후, cors를 api route에 더해주면 된다.

import Cors from 'cors'

// Initializing the cors middleware
const cors = Cors({
  methods: ['GET', 'HEAD'],
})

// Helper method to wait for a middleware to execute before continuing
// And to throw an error when an error happens in a middleware
function runMiddleware(req, res, fn) {
  return new Promise((resolve, reject) => {
    fn(req, res, (result) => {
      if (result instanceof Error) {
        return reject(result)
      }

      return resolve(result)
    })
  })
}

async function handler(req, res) {
  // Run the middleware
  await runMiddleware(req, res, cors)

  // Rest of the API logic
  res.json({ message: 'Hello Everyone!' })
}

export default handler

Response Helper

api route의 response는 개발자 환경을 개선시키고, 새로운 api endpoint를 만드는 속도를 높이기 위해, Express.js와 유사한 method set을 포함한다.

res.status(code) : 상태 코드를 설정하는 함수이다. 코드는 유효한 HTTP 상태 코드여야 한다. (보통 200이 성공)
res.json(body) : json 응답을 보낸다. body는 직렬화가능한 객체여야한다.
res.send(body) : HTTP 응답을 전송한다. body는 문자열, 객체, 또는 버퍼일 수 있다.
res.redirect([status,] path) : 지정된 경로, url로 리디렉션된다. status는 유효한 HTTP 상태 코드여야 한다. 지정하지 않을 시, 상태 코드는 307(임시 리디렉션)으로 기본 설정된다.

참고
책은 p.135부터 참고하면 될듯하다. (typescript기반이지만 비슷할듯하다.)

profile
Next.js 씹어먹자

0개의 댓글

관련 채용 정보