[Next.js] Route Handlers

파이리·2023년 8월 2일
0

Next.js

목록 보기
12/18
post-thumbnail

라우터 핸들러를 사용하면 웹 요청 및 응답 API를 사용하여 지정된 라우트에 대한 사용자 지정 요청 핸들러를 만들 수 있습니다.

라우터 핸들러는 앱 디렉터리 내에서만 사용할 수 있습니다. 라우트 핸들러는 페이지 디렉터리 내의 API 경로와 동일하므로 API 경로와 라우트 핸들러를 함께 사용할 필요가 없습니다.

Convention

라우터 핸들러는 앱 디렉터리 내의 route.js 또느 route.ts 파일에 정의됩니다.

export async function GET(request: Request) {}

라우터 핸들러는 page.jslayout.js와 유사하게 앱 디렉터리 내에 중첩될 수 있습니다. 하지만 page.js와 동일한 Route Segment 수준에는 route.js 파일이 있을 수 없습니다.

지원하는 HTTP 메서드

지원하는 HTTP 메서드는 다음과 같습니다. GET, POST, PUT, PATCH, DELETE, HEAD, 그리고 OPTIONS이 있습니다. 지원되지 않는 메서드가 호출되면 Next.js는 405 에러로 메서드가 허용되지 않음 응답을 반환합니다.

확장된 NextRequest 와 NextResponse API

기본 RequestResponse을 지원할 뿐만 아니라, Next.js는 고급 사용 사례를 위한 편리한 도우미를 제공하기 위해 NextRequestNextResponse로 이를 확장합니다.

동작

정적 라우트 핸들러

라우트 핸들러는 기본적으로 응답 객체와 함께 GET 메서드를 사용할 때 정적으로 평가됩니다.

import { NextResponse } from 'next/server'
 
export async function GET() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
  })
  const data = await res.json()
 
  return NextResponse.json({ data })
}

동적 라우트 핸들러

라우터 핸들러는 아래와 같은 상황에서 동적으로 평가됩니다.

  • GET 메서드와 함께 요청 객체를 사용하는 경우

  • 다른 HTTP 메서드를 사용하는 경우

  • 쿠키 및 헤더와 같은 동적 함수를 사용하는 경우

  • 세그먼트 구성 옵션에서 동적 모드를 수동으로 지정합니다.

import { NextResponse } from 'next/server'
 
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const id = searchParams.get('id')
  const res = await fetch(`https://data.mongodb-api.com/product/${id}`, {
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
  })
  const product = await res.json()
 
  return NextResponse.json({ product })
}

또한 POST 메서드를 사용하면 라우트 핸들러가 동적으로 평가됩니다.

import { NextResponse } from 'next/server'
 
export async function POST() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
    body: JSON.stringify({ time: new Date().toISOString() }),
  })
 
  const data = await res.json()
 
  return NextResponse.json(data)
}

Route Resolution

경로를 가장 낮은 수준의 라우팅 프리미티브로 간주할 수 있습니다.

페이지와 같은 레이아웃이나 클라이언트 측 탐색에 참여하지 않습니다.

page.js와 같은 경로에 route.js 파일이 있을 수 없습니다.

Examples

다음 예제에서 라우트 핸들러를 다른 Next.js API 및 기능과 결합하는 방법을 보여줍니다.

정적 데이터 재검증

next.revalidate 옵션을 사용하여 정적 데이터 가져오기의 유효성을 재검증할 수 있습니다.

import { NextResponse } from 'next/server'
 
export async function GET() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    next: { revalidate: 60 }, // Revalidate every 60 seconds
  })
  const data = await res.json()
 
  return NextResponse.json(data)
}

또는 세그먼트 구성 재검증 옵션을 사용할 수도 있습니다.

export const revalidate = 60

동적 함수

라우터 핸들러는 쿠키 및 헤더와 같은 Next.js의 동적 함수와 함께 사용할 수 있습니다.

쿠키

next/headerscookies 프로퍼티를 통해 쿠키를 읽을 수 있습니다. 이 서버 함수는 라우트 핸들러에서 직접 호출하거나 다른 함수 내부에 중첩할 수 있습니다.

이 쿠키 인스턴스는 읽기 전용입니다. 쿠키를 설정하려면 Set-cookie 헤더를 사용하여 새 응답을 반환해야 합니다.

import { cookies } from 'next/headers'
 
export async function GET(request: Request) {
  const cookieStore = cookies()
  const token = cookieStore.get('token')
 
  return new Response('Hello, Next.js!', {
    status: 200,
    headers: { 'Set-Cookie': `token=${token.value}` },
  })
}

또는 기본 Web APIs 위에 추상화를 사용하여 쿠키를 읽을 수 있습니다.

import { type NextRequest } from 'next/server'
 
export async function GET(request: NextRequest) {
  const token = request.cookies.get('token')
}

헤더

next/headers를 통해 headers을 읽을 수 있습니다. 이 서버 함수는 라우트 핸들러에서 직접 호출하거나 다른 함수 내부에 중첩할 수 있습니다.

이 헤더 인스턴스는 읽기 전용입니다. 헤더를 설정하려면 새 헤더가 포함된 새 응답을 반환해야 합니다.

import { headers } from 'next/headers'
 
export async function GET(request: Request) {
  const headersList = headers()
  const referer = headersList.get('referer')
 
  return new Response('Hello, Next.js!', {
    status: 200,
    headers: { referer: referer },
  })
}

또는 기본 Web APIs 위에 추상화를 사용하여 헤를 읽을 수 있습니다.

import { type NextRequest } from 'next/server'
 
export async function GET(request: NextRequest) {
  const requestHeaders = new Headers(request.headers)
}

리다이렉트

import { redirect } from 'next/navigation'
 
export async function GET(request: Request) {
  redirect('https://nextjs.org/')
}

동적 라우트 세그먼트

라우트 핸들러는 동적 세그먼트를 사용하여 동적 데이터에서 요청 핸들러를 생성할 수 있습니다.

export async function GET(
  request: Request,
  { params }: { params: { slug: string } }
) {
  const slug = params.slug // 'a', 'b', or 'c'
}

스트리밍

스트리밍은 일반적으로 AI 생성 콘텐츠에 OpenAI와 같은 대규모 언어 모델과 함께 사용됩니다.

import { Configuration, OpenAIApi } from 'openai-edge'
import { OpenAIStream, StreamingTextResponse } from 'ai'
 
const config = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
})
const openai = new OpenAIApi(config)
 
export const runtime = 'edge'
 
export async function POST(req: Request) {
  const { prompt } = await req.json()
  const response = await openai.createCompletion({
    model: 'text-davinci-003',
    stream: true,
    temperature: 0.6,
    prompt: 'What is Next.js?',
  })
 
  const stream = OpenAIStream(response)
  return new StreamingTextResponse(stream)
}

이러한 추상화는 Web API를 사용하여 스트림을 생성합니다. 기본 Web API를 직접 사용할 수도 있습니다.

function iteratorToStream(iterator: any) {
  return new ReadableStream({
    async pull(controller) {
      const { value, done } = await iterator.next()
 
      if (done) {
        controller.close()
      } else {
        controller.enqueue(value)
      }
    },
  })
}
 
function sleep(time: number) {
  return new Promise((resolve) => {
    setTimeout(resolve, time)
  })
}
 
const encoder = new TextEncoder()
 
async function* makeIterator() {
  yield encoder.encode('<p>One</p>')
  await sleep(200)
  yield encoder.encode('<p>Two</p>')
  await sleep(200)
  yield encoder.encode('<p>Three</p>')
}
 
export async function GET() {
  const iterator = makeIterator()
  const stream = iteratorToStream(iterator)
 
  return new Response(stream)
}

Request Body

표준 Web APIs 메서드를 사용하여 요청 Body을 읽을 수 있습니다.

import { NextResponse } from 'next/server'
 
export async function POST(request: Request) {
  const res = await request.json()
  return NextResponse.json({ res })
}

CORS

표준 Web APIs 메서드를 사용하여 Response에 CORE 헤더를 설정할 수 있습니다.

export async function GET(request: Request) {
  return new Response('Hello, Next.js!', {
    status: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    },
  })
}

Edge 및 Node.js 런타임

라우트 핸들러에는 스트리밍 지원을 포함하여 Edge와 Node.js 런타임을 모두 원활하게 지원하는 동형 Web API가 있습니다. 라우터 핸들러는 페이지 및 레이아웃과 동일한 라우트 세그먼트 구성을 사용하기 때문에 범용 정적으로 재생성되는 라우트 핸들러와 같이 오랫동안 기다려온 기능을 지원합니다.

runtime 세그먼트 구성 옵션을 사용하여 런타임에 지정할 수 있습니다.

export const runtime = 'edge' // 'nodejs' is the default

Non-UI Responses

라우터 핸들러를 사용하여 Non-UI 컨텐츠를 반환할 수 있습니다. sitemap.xml , robots.txt, app icons 그리고 오픈 그래프 이미지 모두 기본 지원됩니다

export async function GET() {
  return new Response(`<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
 
<channel>
  <title>Next.js Documentation</title>
  <link>https://nextjs.org/docs</link>
  <description>The React Framework for the Web</description>
</channel>
 
</rss>`)
}

세그먼트 구성 옵션

라우트 핸들러는 페이지 및 레이아웃과 동일한 라우트 세그먼트 구성을 사용합니다.

export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'
profile
프론트엔드 개발자

0개의 댓글