에듀테크 프로젝트 대시보드
CORS (교차 출처 리소스 공유)
브라우저는 기본적으로 같은 출처(origin)의 응답만 자바스크립트가 읽게 해준다(동일 출처 정책·SOP). CORS는 서버가 특정 헤더로 "이 출처는 허용해"라고 명시적으로 허락해 주는 규칙이다. 서버가 아니라 브라우저가 강제한다는 점이 핵심.
OPTIONS 프리플라이트로 허락을 받아야 한다.
출처 = 스킴 + 호스트 + 포트 세 가지의 조합. 하나라도 다르면 "교차 출처(cross-origin)"다. 경로(path)·쿼리·프래그먼트는 출처와 무관하다.
기준 URL: https://shop.example.com/page | 같은 출처? | 이유 |
|---|---|---|
| https://shop.example.com/other/path | O | 경로만 다름 — 출처는 동일 |
| http://shop.example.com/page | X | 스킴 다름 (https ≠ http) |
| https://api.example.com/page | X | 호스트 다름 (서브도메인도 별개) |
| https://shop.example.com:8443/page | X | 포트 다름 |
프런트엔드는 https://app.mysite.com 에서 실행 중이라고 하자. 아래에서 요청 조건과 서버가 내려주는 CORS 헤더를 바꿔 가며, 브라우저가 응답을 넘겨줄지 막을지 확인해 보자.
브라우저는 요청이 단순 요청(simple request) 조건을 모두 만족하면 바로 보낸다. 하나라도 어기면 먼저 OPTIONS 프리플라이트를 보내 서버에 허락을 구한다.
| 조건 | 단순 요청 SIMPLE | 프리플라이트 PREFLIGHT |
|---|---|---|
| 메서드 | GET, HEAD, POST | PUT, DELETE, PATCH ... |
| Content-Type | text/plain · form-urlencoded · multipart/form-data | application/json 등 |
| 사용자 정의 헤더 | 없음 (기본 헤더만) | X-Auth-Token 등 추가 |
DELETE 를 던지면
서버가 실제로 데이터를 지워버릴 수 있다. 그래서 "부작용이 있을 법한" 요청은 먼저 OPTIONS로 물어보고,
서버가 명시적으로 "그 메서드·그 헤더 허용해"라고 답할 때만 본 요청을 보낸다.
# 1) 브라우저가 자동으로 보내는 프리플라이트 OPTIONS /data HTTP/1.1 Host: api.mysite.com Origin: https://app.mysite.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: x-auth-token, content-type # 2) 서버 응답 — "그 조건이면 허용" HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://app.mysite.com Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: X-Auth-Token, Content-Type Access-Control-Max-Age: 600 # 10분간 프리플라이트 캐시 # 3) 이제서야 실제 PUT 요청이 나간다 PUT /data HTTP/1.1 Origin: https://app.mysite.com X-Auth-Token: abc123 Content-Type: application/json
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins=["https://app.mysite.com"], # "*" 는 credentials 와 함께 못 씀 allow_credentials=True, allow_methods=["*"], allow_headers=["X-Auth-Token", "Content-Type"], max_age=600, )
Allow-Credentials: true" 는
사실상 아무 사이트나 쿠키를 실어 요청하게 허용하는 구멍이다. 허용 목록(allowlist)을 명시하자.
Access-Control-Allow-Origin: * 와 credentials 는 동시에 쓸 수 없다(브라우저가 거부).
canvas로 읽거나 모듈로 쓰면 CORS가 필요.