FastAPI to React CORS 오류
✒️ 2026-03-01 13:01 내용 수정
📋 문제 개요
문제 설명
프론트엔드 로컬 환경과 배포된 FastAPI 서버간 API 요청 연결 안됨.

사진을 보면 400코드를 받은 상태고, 현재 서버에선 CORS 미들웨어로 특정 클라이언트 요청만 받도록 설정해둔 상태다.
다만 개발 환경에서 Render로 배포된 FastAPI로 React 로컬에서의 요청을 전송할 때 CORS로 요청이 전송되지 않았다.
React 로컬의 IP 주소를 허용 origin 목록에 넣어도 문제가 해결되지 않았다.

🔍 상세 정보
발생 환경
- 환경: 배포, 개발
- 서버/인스턴스: Render, FastAPI, Vercel
- 브라우저/디바이스: Chrome
재현 방법
- FastAPI의 CORS 설정 중 허용할 Origin 설정(
allow_origins)에 IP 주소만 입력
에러 메시지 및 로그
- 서버 측 요청 로그

🔎 원인 분석
조사 과정
- MS Copilot으로 문제 분석
- [JavaScript] Access to fetch at... has been blocked by CORS policy 오류 해결 방법

근본 원인
허용할 Origin 목록에 로컬 환경 IP 주소가 아닌 Request Header에 표기되는 Origin 을 작성해야 함.
✅ 해결 방법
적용한 솔루션
- 로컬 React에서 배포된 서버(Render)로 요청 전송 시 실제 해결 방법을 적용하였고,
allow_origins가 와일드 카드(*)가 아닌 상태에도 동작하는 것을 확인 - 배포된 프론트엔드(Vercel)에서도 같은 방법으로
Origin을 등록했을 때 배포된 서버(Render)로 요청이 잘 되는 것을 확인함
임시 조치 (Workaround)
- 서버의 CORS의 설정 변경
allow_origins을 와일드 카드(*)로 설정하여 모든 Origin 허용allow_credentials = False로 임시 변경allow_methods에OPTIONS추가allow_headers=["Access-Control-Request-Method"]를 추가
- Origin을 검증하는
verify_origin함수에서 모든 Origin을 허용
# main.py
# CORS 미들웨어 등록
app.add_middleware(
CORSMiddleware,
allow_origins=allowed_origins,
allow_credentials=False, # 임시 해결 조치
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["Content-Type", "Authorization", "Access-Control-Request-Method"],
)
# app/routes/deps.py
# 서버단 ORIGIN 필터
def verify_origin(request: Request):
settings = get_settings()
allowed = set(parse_origins(getattr(settings, "client_origin", "")))
# 생략...
if "*" in allowed:
if origin: # 브라우저 요청
return
# .env
# 프론트엔드 연동 설정
CLIENT_ORIGIN="*"
실제 해결 방법
- 서버측에서 허용할
CLIENT_ORIGIN에http://localhost:port로 추가해야 함 - 배포된 프론트엔드 도메인도 등록하여 배포된 프론트엔드-백엔드간의 API 요청을 허용하도록 설정
# .env
CLIENT_ORIGIN="http://localhost:5173, 프론트엔드_도메인"
- 오류가 발생했던 요청에서 개발자 도구로 Request Headers를 봤을 때
Origin이 특정 컴퓨터의 ip 주소가 아니라http://localhost:5173으로 표기되며, 이 값을 허용Origin목록에 넣어야 정상적으로 통과됨

- 전체 Origin 설정 부분은 와일드카드(
*)를 제거하고 프론트엔드 도메인과 프론트엔드 로컬만 허용하도록 변경
# main.py
# CORS 미들웨어 등록
app.add_middleware(
CORSMiddleware,
allow_origins=allowed_origins,
allow_credentials=True, # 보안 필수
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["Content-Type", "Authorization", "Access-Control-Request-Method"],
)
# app/routes/deps.py
# 서버단 ORIGIN 필터
def verify_origin(request: Request):
settings = get_settings()
allowed = set(parse_origins(getattr(settings, "client_origin", "")))
# 생략...
"""
아래 부분을 다시 제거
if "*" in allowed:
if origin: # 브라우저 요청
return
"""