Next.js API Routes 어떻게 활용하면 좋을까?

bongbong·2024년 6월 22일
1

Next.js

목록 보기
1/6
post-thumbnail

API Routes

Next.js로 public API를 구축할 수 있는 솔루션을 제공

pages/api 폴더 내의 모든 파일은 /api/*에 매핍되어 페이지 대신 API 엔드포인트로 처리되며 이는 서버 측 전용 번들이며 클라이언트 측 번들 크기를 늘리지 않는다.

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!' })
}

특징

  • 기본적으로 Next.js의 API는 같은 웹사이트에서만 접근할 수 있다.(same-origin only)
  • 다른 웹사이트에서도 접근 가능하게 하려면 CORS 설정을 해줘야 한다.(CORS request helper로 가능)
  • 통합된 프로젝트 구조로 프론트엔드와 백엔드 코드가 동일한 프로젝트 내에 있어 코드 관리가 용이하다.
  • 별도의 서버 설정 없이 API 구축이 가능하다
  • 데이터베이스, 외부 API 등 다양한 소스에서 데이터를 가져오거나 처리할 수 있다.
  • 간단한 데이터 처리에는 적합하지만 복잡한 비즈니스 로직이나 대규모 애플리케이션에 한계가 있다.
  • 높은 트래픽을 처리할 때 서버 성능 저하가 발생할 수 있다.

HTTP Methods

API 경로에서 다양한 HTTP 메소드를 처리하려면 다음과 같이 요청 핸들러에서 req.method를 사용할 수 있다.

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

API Routes는 들어오는 요청(req)을 파싱하는 request helpers를 제공한다.

  • req.cookies : reqeust에 의해 전송된 쿠기를 포함하는 객체
  • req.query : url의 query string
  • req.body : content-type에 따라 파싱된 body

Response Helpers

Server Response object는 개발자 경험을 개선하고 새로운 API 엔드포인트를 더 빨리 생성할 수 있도록 하기 위해 express.js와 유사한 여러 helper methods를 포함한다.

  • res.status(code) : HTTP status code를 설정한다. code는 유효한 HTTP 상태 코드여야한다.
  • res.json(body) : JSON 응답을 보낸다. body는 직렬화 가능한 객체여야 한다.
  • res.send(body) : HTTP 응답을 보낸다. body는 문자열, 객체 or buffer일 수 있다.
  • res.redirect([status,] path) : 지정된 경로 또는 URL로 리디렉션한다.
  • res.revalidate(urlPath) : getStaticProps를 사용하여 페이지를 다시 검증한다.

API Routes 어떻게 활용하면 좋을까?

1. Form validation

API Routes는 클라이언트와 서버 간의 데이터를 주고받는 데 유용. 예를 들어, 사용자로부터 폼 데이터를 받아 서버에서 처리할 때 사용할 수 있다.

데이터 무결성 보장: 서버 측 검증은 클라이언트가 어떤 환경에서든지 잘못된 데이터를 서버에 전송하지 못하도록 합니다. 이는 데이터베이스에 저장되는 데이터의 품질과 무결성을 보장하는 데 중요합니다

// pages/api/submit.js
import type { NextApiRequest, NextApiResponse } from 'next'
import { z } from 'zod'
 
const schema = z.object({
  // ...
})
 
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const parsed = schema.parse(req.body)
  // ...
}

2. 외부 서비스 URL 숨기기

API 라우트를 사용하면 클라이언트 사이드에서 바로 외부 API를 호출하지 않고, 내 서버를 거치게 하여 외부 서비스의 URL이나 키 같은 민감한 정보를 숨길 수 있습니다. 이는 보안상의 이점을 갖습니다.

외부 API를 숨기는 것은 보안과 데이터 보호 측면에서 여러 가지 이점을 제공합니다. Next.js API Routes를 사용하여 외부 API 호출을 서버 측에서 처리함으로써 다음과 같은 상황에서 이점을 얻을 수 있습니다:

API 키 보호:

상황: 여러분의 애플리케이션이 외부 서비스(API)를 사용해야 하고, 이 서비스에 접근하기 위해 API 키가 필요하다면, 이 API 키를 클라이언트 코드에 직접 포함시키는 것은 위험할 수 있습니다. 사용자가 API 키를 쉽게 추출할 수 있기 때문입니다.
이점: Next.js API Routes에서 외부 API를 호출함으로써 API 키를 서버 측에 안전하게 보관할 수 있습니다. 클라이언트는 API 키를 전혀 알 필요가 없습니다.
요청 및 응답 변환:

상황: 외부 API의 응답 형식이 클라이언트 애플리케이션에 적합하지 않을 수 있습니다. 예를 들어, 외부 API가 너무 많은 데이터를 반환하거나 필요한 형식으로 데이터를 반환하지 않는 경우가 있습니다.
이점: Next.js API Routes에서 외부 API의 응답을 변환하여 클라이언트가 필요한 데이터만 전달할 수 있습니다. 이를 통해 데이터의 크기를 줄이고 클라이언트의 처리 부담을 줄일 수 있습니다.
보안 및 접근 제어:

상황: 특정 사용자만 외부 API에 접근할 수 있도록 제한해야 하는 경우가 있습니다.
이점: Next.js API Routes에서 사용자 인증 및 권한 검사를 수행한 후에 외부 API를 호출할 수 있습니다. 이를 통해 인증되지 않은 사용자가 외부 API에 접근하는 것을 방지할 수 있습니다.

3. 데이터 필터링 및 가공

서버에서 데이터 변환이나 처리가 필요한 경우 API Routes를 사용할 수 있습니다. 예를 들어, 외부 API로부터 데이터를 가져와서 클라이언트에 맞게 변환한 후 제공할 수 있습니다.

클라이언트에서 직접 외부 API를 호출하는 대신, 서버에서 API 요청을 중계하고 응답 데이터를 필터링하거나 가공하여 클라이언트에 전달할 수 있습니다. 이는 네트워크 트래픽을 줄이고, 클라이언트 애플리케이션의 성능을 향상시킬 수 있습니다.

// pages/api/external-data.js
export default async (req, res) => {
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();

  // 데이터 변환
  const transformedData = data.map(item => ({
    id: item.id,
    name: item.name.toUpperCase(),
  }));

  res.status(200).json(transformedData);
};

4. 인증 및 권한 관리

API Routes를 통해 사용자 인증 및 권한 관리를 구현할 수 있습니다. 예를 들어, 토큰을 검증하여 사용자가 인증된 상태인지 확인할 수 있습니다.
사용자 인증: 사용자의 로그인 요청을 처리하기 위해 API 라우트를 사용하여 서버측에서 사용자의 인증을 처리하고, 인증 토큰을 클라이언트에 전달할 수 있습니다.

// pages/api/protected.js
import jwt from 'jsonwebtoken';

export default (req, res) => {
  const { authorization } = req.headers;

  if (!authorization) {
    return res.status(401).json({ message: 'No token provided' });
  }

  try {
    const decoded = jwt.verify(authorization.split(' ')[1], 'secret-key');
    res.status(200).json({ message: 'Authenticated', user: decoded });
  } catch (error) {
    res.status(401).json({ message: 'Invalid token' });
  }
};

5. 서버 측 기능 제공

서버 측에서만 사용할 수 있는 특정 기능(예: 파일 시스템 접근, 데이터베이스 쿼리 등)을 API Routes를 통해 제공할 수 있습니다.

// pages/api/upload.js
import formidable from 'formidable';

export default (req, res) => {
  if (req.method === 'POST') {
    const form = new formidable.IncomingForm();
    form.parse(req, (err, fields, files) => {
      if (err) {
        return res.status(500).json({ message: 'File upload error' });
      }
      
      // 예: 파일 처리
      // const file = files.file;
      // fs.renameSync(file.path, `/uploads/${file.name}`);

      res.status(200).json({ message: 'File uploaded successfully' });
    });
  } else {
    res.status(405).json({ message: 'Method not allowed' });
  }
};

6. CORS 우회

API Routes를 serverside에서 호출하는 것을 성능상 비효율적.

Reference

0개의 댓글