2026. 6. 26.
fetch CORS 오류, no-cors 전에 브라우저와 서버를 가르는 확인 순서
AI가 만든 React·Next.js 화면의 fetch가 CORS로 막혔을 때 origin, 실패 요청, 서버 응답 헤더, credentials를 확인해 수정할 경계를 좁히는 순서다.

AI가 만든 React나 Next.js 화면에서 fetch를 실행했는데 콘솔에 blocked by CORS policy가 뜨면 프론트 코드를 전부 다시 만들기 쉽습니다. 먼저 할 일은 mode: "no-cors"를 붙이는 것이 아닙니다. 프론트 출처, API 주소, 실패한 요청, 서버 응답 헤더를 기록해 브라우저 요청과 서버 허용 응답 중 어디가 막혔는지 나눠야 합니다.
판단 기준은 간단합니다. 요청 주소나 method가 틀렸다면 클라이언트에서 고치고, 요청은 맞지만 허용 헤더가 없다면 API 서버나 프록시에서 고칩니다. OPTIONS만 실패하면 preflight 처리부터 봅니다. 이 경계를 정한 뒤에야 AI에게 바꿀 파일을 제한할 수 있습니다.
CORS는 프론트 옵션보다 서버 응답을 먼저 봅니다
MDN의 CORS 가이드는 CORS를 서버가 어떤 출처의 브라우저에 응답 읽기를 허용할지 알리는 HTTP 헤더 기반 장치로 설명합니다. 브라우저의 같은 출처 정책이 기본적으로 교차 출처 스크립트 요청을 제한하고, 서버의 올바른 CORS 응답이 있을 때만 JavaScript가 응답을 읽을 수 있습니다.
여기서 출처는 도메인만 뜻하지 않습니다. scheme, host, port 조합이 달라지면 다른 출처입니다. 같은 컴퓨터라도 http://localhost:3000에서 http://localhost:4000으로 요청하면 교차 출처 요청입니다.
프론트 출처: http://localhost:3000
API 주소: http://localhost:4000/api/todos
이 둘이 다르면 CORS가 필요한 상황인지 확인합니다. 반대로 같은 출처인데 CORS처럼 보이는 오류가 난다면 redirect, 프록시, 잘못된 환경변수 때문에 실제 요청이 다른 도메인으로 갔는지도 Network 패널에서 확인합니다.
mode: "no-cors"는 JSON 응답을 읽게 해 주는 해결책이 아닙니다. MDN의 Request mode 문서에 따르면 no-cors 응답은 opaque가 되어 JavaScript에서 상태, 헤더, 본문을 읽을 수 없습니다. 요청을 숨긴 채 성공처럼 보이게 만드는 대신, 서버 허용 정책과 요청 조건을 고쳐야 합니다.
Network에서 네 칸을 채우면 수정 경계가 보입니다
개발자 도구의 Network 탭을 열고 실패한 요청을 선택합니다. 오류 메시지 전체를 AI에게 붙이기 전에 아래 네 칸만 먼저 채웁니다.
1. 프론트 출처:
2. Request URL / Method:
3. 실패한 요청: OPTIONS 또는 실제 GET·POST 등
4. Response Headers의 Access-Control-Allow-*:
결과는 다음처럼 나눕니다.
| 관찰 | 먼저 볼 곳 | 이유 |
|---|---|---|
| Request URL이나 method가 예상과 다름 | fetch 호출부·환경변수 | 클라이언트가 다른 경로를 요청하고 있습니다. |
실제 요청 응답에 Access-Control-Allow-Origin이 없음 | API 서버·프록시 | 브라우저에 읽기 권한을 알리는 서버 응답이 없습니다. |
OPTIONS가 404·405 또는 헤더 없이 실패 | 서버의 preflight 처리 | 실제 요청 전에 허용 여부 확인이 막혔습니다. |
| 쿠키 포함 요청만 실패 | client credentials와 server allow 정책 | 명시적인 origin과 credentials 허용이 함께 필요합니다. |
| 제어할 수 없는 외부 API가 허용 헤더를 주지 않음 | 소유한 서버 프록시 또는 공식 API 방식 | 브라우저 클라이언트가 외부 서버의 허용 헤더를 대신 만들 수 없습니다. |
API 요청 자체가 404나 405라면 CORS와 상태 코드를 섞어 보지 마세요. Next.js API 404와 405를 나누는 점검법처럼 먼저 URL·method·status를 맞춘 다음 CORS 응답을 확인하는 편이 빠릅니다.
OPTIONS가 실패하면 실제 요청보다 preflight를 고칩니다
교차 출처 요청 중 일부는 실제 요청 전에 브라우저가 OPTIONS 요청을 보냅니다. 이를 preflight라고 합니다. 서버가 요청 method와 header를 허용하는지 미리 확인하는 단계입니다.
OPTIONS가 실패했는데 POST 함수만 계속 고치면 실제 POST는 시작조차 하지 않을 수 있습니다. Network에서 OPTIONS를 열고 다음 응답 헤더를 확인합니다.
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET,POST,OPTIONS
Access-Control-Allow-Headers: Content-Type
필요한 값은 API의 실제 정책에 따라 달라집니다. 보이지 않는다고 모든 origin과 header를 무조건 허용하지 마세요. 허용할 프론트 도메인, method, header를 서버에서 명시하는 편이 안전합니다.
현재 Next.js Route Handler 문서는 OPTIONS를 지원하고, 직접 정의하지 않으면 다른 handler를 기준으로 Allow 헤더를 포함한 OPTIONS 응답을 자동 구현한다고 설명합니다. 다만 HTTP Allow와 CORS의 Access-Control-Allow-*는 같은 것이 아닙니다. 교차 출처 API라면 필요한 CORS 응답 헤더를 정책에 맞게 따로 확인해야 합니다.
const allowedOrigin = "https://app.example.com";
export async function OPTIONS() {
return new Response(null, {
status: 204,
headers: {
"Access-Control-Allow-Origin": allowedOrigin,
"Access-Control-Allow-Methods": "GET,POST,OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
"Vary": "Origin",
},
});
}
이 코드는 헤더를 두는 위치를 보여 주는 예시입니다. 실제 서비스에서는 환경별 허용 목록, 프록시·CDN 동작, 인증 방식까지 함께 검토합니다.
쿠키나 인증이 있으면 wildcard를 멈춥니다
credentials: "include"를 쓰거나 쿠키·인증 정보를 포함한 요청은 비인증 요청과 조건이 다릅니다. MDN의 credentials 헤더 문서는 서버가 credentialed 요청을 허용한다는 응답을 명시해야 한다고 설명합니다.
fetch("https://api.example.com/profile", {
credentials: "include",
});
이때 서버가 Access-Control-Allow-Origin: *만 반환하면 브라우저가 응답 접근을 막습니다. 쿠키나 인증이 포함되면 정확한 허용 origin과 Access-Control-Allow-Credentials: true를 함께 검토합니다. private API를 빨리 열겠다고 wildcard를 붙이는 방식은 피합니다.
AI에게 로그를 보낼 때도 실제 cookie, token, Authorization 값은 삭제합니다. 필요한 정보는 “인증 포함 여부”, header 이름, 프론트와 API의 origin입니다. 값 자체가 아닙니다.
AI에게는 전체 수정이 아니라 경계 판단을 요청합니다
네 칸을 채웠다면 아래 프롬프트로 수정 범위를 좁힙니다.
React/Next.js 화면의 fetch가 CORS로 막힙니다.
프론트 출처:
[origin]
Request URL / Method:
[URL과 method]
실패한 요청:
[OPTIONS 또는 실제 요청]
CORS 응답 헤더:
[헤더 이름과 존재 여부만]
인증 포함 여부:
[없음 / cookie / Authorization, 실제 값은 제외]
요청:
1. 클라이언트 요청 오류와 서버 CORS 응답 오류를 먼저 나눠 주세요.
2. mode: "no-cors"를 JSON 응답 해결책으로 제안하지 마세요.
3. 가장 가능성 높은 원인과 확인할 파일을 먼저 제시하세요.
4. 바꿀 파일은 최대 2개로 제한하고, 변경 후 Network 확인 순서를 주세요.
AI 답변을 받으면 바로 적용하지 않습니다. 변경 파일, 새로 열린 origin, 삭제된 보안 검사, 새 환경변수를 먼저 봅니다. AI에게 오류를 다시 묻는 기본 형식이 필요하다면 AI 코드 오류를 다시 질문하는 네 칸과 함께 사용해도 좋습니다.
끝에는 같은 요청을 다시 보내 확인합니다
수정 뒤에는 화면이 한 번 열렸다는 사실만 보지 않습니다. 같은 버튼이나 동작을 다시 실행하고 Network에서 확인합니다.
- 실제 요청이 예상 URL과 method로 갔는가
OPTIONS가 있다면 성공하고 실제 요청이 이어졌는가- 서버 응답의 허용 origin이 현재 프론트와 일치하는가
- JavaScript가 필요한 상태·헤더·본문을 읽는가
- 인증 요청에서 wildcard나 비밀값 노출이 없는가
이 다섯 항목이 확인되기 전에는 CORS 오류를 해결했다고 판단하지 않습니다. 지금 오류가 떠 있다면 코드를 다시 만들기 전에 출처, API 주소, 실패 요청, 응답 헤더를 먼저 채우세요. 그 기록이 프론트와 서버 중 어디를 고칠지 가르는 가장 작은 결과물입니다.
공식 확인 링크
- Cross-Origin Resource Sharing (CORS), MDN
- Request: mode, MDN
- CORS header Access-Control-Allow-Origin missing, MDN
- Access-Control-Allow-Credentials, MDN
- Route Handlers, Next.js
이 글은 AI 코딩과 개발 학습의 일반 정보 제공 목적입니다. 도구, 모델, 커리큘럼, 요금은 버전과 시점에 따라 달라질 수 있으므로 실습이나 도입 전 공식 문서와 최신 릴리스 노트를 확인하세요.
다음으로 읽을 기사
같은 흐름으로 이어 읽기 좋은 기사만 추려 보여줍니다.
첫 번째 댓글을 남겨보세요
여러분의 생각이 다른 독자에게 도움이 됩니다.
댓글 0
이 글을 읽은 독자들의 생각을 나눠보세요.