이 글에서 정리하는 내용
Next.js Route Handler 405 오류는 API 코드가 없어서가 아니라 요청한 HTTP 메서드와 route.ts에서 export한 메서드가 맞지 않을 때 생깁니다. 파일 위치, GET/POST export, 요청 URL, trailing slash, form method를 같이 확인해야 합니다.
Route Handler 파일 위치가 맞는데도 배포 후 경로가 다르게 동작한다면 Vercel 404 NOT_FOUND 라우팅 오류 해결도 함께 확인해 API 라우팅과 rewrites 문제를 분리해야 합니다.
- 내 증상이 이거면 여기부터 보세요
- 먼저 적용할 핵심 수정 코드
- 왜 이런 오류가 생기는가
- 실제 작업에서 점검하는 순서
- 그래도 안 될 때 볼 예외 케이스
- 다음에 같은 문제를 줄이는 체크리스트
내 증상이 이거면 여기부터 보세요

App Router에서는 pages/api가 아니라 app/api/…/route.ts 파일이 API 엔드포인트가 됩니다. 파일은 있는데 405가 난다면 보통 경로는 맞지만 해당 메서드를 처리하는 함수가 없는 상태입니다.
| 증상 | 실제 에러 메시지 | 먼저 볼 위치 | 바로 해볼 조치 | 이동할 섹션 |
|---|---|---|---|---|
| GET 요청이 405 | 405 Method Not Allowed | route.ts export | export async function GET 추가 | 핵심 수정 코드 |
| POST 요청이 405 | Method Not Allowed | form/fetch method | POST 함수와 fetch method 일치 | 핵심 수정 코드 |
| default export 경고 | Detected default export | route.ts 작성 방식 | default 대신 named export 사용 | 왜 생기는가 |
| URL은 맞는데 계속 404/405 | route path mismatch | app/api 경로 | 폴더 구조와 요청 URL 대조 | 예외 케이스 |
오류 해결 글에서는 실제 에러 문구가 본문에 있어야 검색해서 다시 찾기 쉽습니다. 프로젝트명, 사용자명, 토큰, 절대 경로처럼 민감하거나 불필요한 값은 빼고 대표 문구만 남깁니다.
405 Method Not Allowed
No HTTP methods exported in route.ts. Export a named export for each HTTP method.
Detected default export in route.ts. Export a named export for each HTTP method instead.
먼저 적용할 핵심 수정 코드
원인 설명을 오래 읽기 전에 아래 설정부터 현재 코드와 대조해보세요. route.ts에서 요청에 맞는 GET 또는 POST 함수를 named export로 내보내고, 클라이언트 요청 URL과 메서드를 같이 맞춥니다. 중요한 것은 오류를 덮는 옵션을 추가하는 것이 아니라, 실행 환경과 설정 파일이 같은 기준으로 동작하게 만드는 것입니다.
GET/POST Route Handler 기본형
import { NextResponse } from "next/server"
export async function GET() {
return NextResponse.json({ ok: true })
}
export async function POST(request: Request) {
const body = await request.json()
return NextResponse.json({ received: body })
}
Route Handler는 default export가 아니라 HTTP 메서드 이름과 같은 named export를 사용합니다.
클라이언트 요청 메서드 확인
await fetch("/api/contact", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email }),
})
클라이언트가 POST로 보내는데 route.ts에는 GET만 있으면 경로가 맞아도 405가 납니다.
왜 이런 오류가 생기는가
405는 경로가 없다는 뜻이 아니라 경로는 찾았지만 해당 메서드를 허용하지 않는다는 뜻입니다. 그래서 404보다 Route Handler 내부 export를 먼저 봐야 합니다.
App Router의 API 파일은 app/api/contact/route.ts처럼 route.ts 이름을 써야 합니다. app/api/contact.ts처럼 pages router 방식과 섞으면 기대한 URL이 만들어지지 않습니다.
GET 함수와 POST 함수는 같은 route.ts 안에 함께 둘 수 있습니다. 다만 클라이언트 fetch, form method, 서버 export가 같은 메서드 기준으로 맞아야 합니다.
실제 작업에서 점검하는 순서
첫 번째로 오류가 나온 단계를 나눕니다. 개발 서버에서만 보이는지, 빌드에서 실패하는지, 배포나 CI에서만 실패하는지에 따라 봐야 할 파일이 달라집니다. 같은 메시지라도 실행 위치가 다르면 원인도 다를 수 있습니다.
두 번째로 한 번에 여러 설정을 바꾸지 않습니다. Next.js Route Handler 405 오류를 해결하다 보면 관련 파일을 전부 고치고 싶어지지만, 그러면 어떤 변경이 실제 해결책이었는지 알기 어렵습니다. 핵심 설정 하나를 바꾸고 검증 명령을 실행한 뒤 다음 설정으로 넘어가야 합니다.
세 번째로 저장소에 남는 기준으로 정리합니다. 개인 PC에서만 통과하는 임시 조치가 아니라 설정 파일, 패키지 버전, 배포 설정처럼 팀원이 같은 기준으로 재현할 수 있는 형태가 되어야 합니다.
그래도 안 될 때 볼 예외 케이스
기본 수정 후에도 같은 메시지가 남는다면 캐시, 버전 차이, 경로 대소문자, 실행 위치를 같이 봐야 합니다. 오류 메시지는 하나처럼 보여도 실제로는 개발 서버, 타입 검사, 번들러, 배포 환경이 서로 다른 설정을 읽어서 생기는 경우가 많습니다.
- 브라우저 주소창으로 직접 열면 GET 요청입니다. POST만 만든 API를 주소창에서 열면 405가 정상일 수 있습니다.
- middleware가 요청을 가로채면 Route Handler에 도달하기 전 다른 응답이 나올 수 있습니다.
- Next.js 캐시나 배포 환경에서 오래된 route가 남았다면 로컬 build와 배포 로그를 함께 봅니다.
다음에 같은 문제를 줄이는 체크리스트

Route Handler 오류는 파일 위치와 메서드 이름을 함께 봐야 빠르게 잡힙니다. 특히 GET으로 테스트하고 POST만 만든 API를 고장으로 오해하는 경우가 많으니 요청 방법부터 분리하는 습관이 필요합니다.
- app/api/…/route.ts 구조인지 확인합니다.
- default export가 아니라 GET/POST named export를 사용합니다.
- fetch나 form의 method와 서버 export를 맞춥니다.
- 브라우저 주소창 테스트는 GET이라는 점을 기억합니다.
결국 Next.js Route Handler 405 오류는 한 줄짜리 우회 코드보다 확인 순서가 중요합니다. 에러 문구를 단계별로 나누고, 설정 파일과 실행 명령을 같은 기준으로 맞추면 같은 문제를 훨씬 짧게 끝낼 수 있습니다.