본문 바로가기
nextjs

[Nextjs 15] Route handler cors 설정

by spare8433 2025. 2. 7.

설명

route handler 를 통한 응답 헤더 cors 설정 방법 공식문서에서는 middleware.ts 및 next.conifg.ts 에서 설정하는 것을 추천



cors 헤더 설명


Access-Control-Allow-Origin

  • 요청을 허용할 출처(origin)를 지정
  • * 는 모든 출처를 허용하지만, 인증된 요청(예: 쿠키 포함 요청)에는 사용 불가합니다.



Access-Control-Allow-Methods

  • 서버가 허용하는 HTTP 메서드(GET, POST, PUT 등)를 지정
  • 기본적으로 서버는 GET, HEAD, POST만 허용



Access-Control-Allow-Headers

  • 클라이언트가 요청할 때 사용할 수 있는 요청 헤더를 지정



Access-Control-Allow-Credentials

  • 인증 정보를 포함한 요청(예: 쿠키, HTTP 인증 헤더)을 허용할지 여부를 설정
  • true로 설정하려면, Access-Control-Allow-Origin은 *가 아닌 특정 출처여야 합니다.





1. route.ts 에서 직접 설정

preflight 확인을 위한 OPTIONS 요청에서 헤더 제대로 지정되지 않은 경우 cors 오류가 발생할 수 있으므로 OPTIONS 요청에 대한 내용을 각각 구현해야 하는 불편함이 존재



import { NextRequest, NextResponse } from "next/server";

export async function GET(req: NextRequest) {
  const response = new NextResponse(JSON.stringify({ message: "Hello" }), {
    status: 200,
  });

  response.headers.set("Access-Control-Allow-Origin", "*");
  response.headers.set("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
  response.headers.set("Access-Control-Allow-Headers", "Content-Type");

  return response;
}





2. middleware.ts 에서 설정

모든 요청에 같은 헤더를 적용 하므로 예로 Access-Control-Allow-Credentials 가 필요하지 않는 요청의 경우를 특정하고 제외하기에 불편함이 있음



// middleware.ts
import { NextRequest, NextResponse } from 'next/server'

const allowedOrigins = ['https://acme.com', 'https://my-app.org']

const corsOptions = {
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Authorization',
}

export function middleware(request: NextRequest) {
  // Check the origin from the request
  const origin = request.headers.get('origin') ?? ''
  const isAllowedOrigin = allowedOrigins.includes(origin)

  // Handle preflighted requests
  const isPreflight = request.method === 'OPTIONS'

  if (isPreflight) {
    const preflightHeaders = {
      ...(isAllowedOrigin && { 'Access-Control-Allow-Origin': origin }),
      ...corsOptions,
    }
    return NextResponse.json({}, { headers: preflightHeaders })
  }

  // Handle simple requests
  const response = NextResponse.next()

  if (isAllowedOrigin) {
    response.headers.set('Access-Control-Allow-Origin', origin)
  }

  Object.entries(corsOptions).forEach(([key, value]) => {
    response.headers.set(key, value)
  })

  return response
}

export const config = {
  matcher: '/api/:path*',
}





3. next.conifg.ts headers (최종 적용 방법)

next.conifg.ts 에서 각 경로에 따라 헤더를 다르게 설정하고 덮어쓸 수 있어 각기 다른 헤더를 적용 가능



import type { NextConfig } from "next";
import { env } from "process";

const allowedOrigin = env.ALLOWED_ORIGIN || "";

// 공통 헤더 형식
const BASIC_HEADERS = [
  {
    key: "Access-Control-Allow-Origin",
    value: allowedOrigin,
  },
  {
    key: "Access-Control-Allow-Methods",
    value: "GET, POST, PUT, DELETE, PATCH, OPTIONS",
  },
  {
    key: "Access-Control-Allow-Headers",
    value: "Content-Type, Authorization",
  },
];

const nextConfig: NextConfig = {
  /* config options here */
  async headers() {
    return [
      // 전체 라우트에 공통헤더 + Access-Control-Allow-Credentials 적용
      {
        source: "/api/:path*",
        headers: [
          {
            key: "Access-Control-Allow-Credentials",
            value: "true",
          },
          ...BASIC_HEADERS,
        ],
      },
      // /api/auth/ 라우트에 공통헤더 적용
      {
        source: "/api/auth/:path*",
        headers: BASIC_HEADERS,
      },
      // /api/auth/login 라우트만 Access-Control-Allow-Credentials 적용
      {
        source: "/api/auth/login",
        headers: [
          {
            key: "Access-Control-Allow-Credentials",
            value: "true",
          },
          ...BASIC_HEADERS,
        ],
      },
    ];
  },
};

export default nextConfig;






참고

https://nextjs.org/docs/app/building-your-application/routing/route-handlers#cors
https://nextjs.org/docs/app/building-your-application/routing/middleware#cors
https://nextjs.org/docs/app/api-reference/config/next-config-js/headers#cors