브라우저가 다른 출처로의 요청을 막는 규칙이고, 서버가 허용 헤더로 풀어줍니다. 조건에 따라 실제 요청 전에 사전 요청(preflight)이 한 번 더 갑니다.
CORS (Cross-Origin Resource Sharing)
브라우저가 다른 출처(origin)의 리소스 요청을 제어하는 보안 메커니즘
출처(Origin)란?
https://api.example.com:443/users
└─┬──┘ └──────┬───────┘└┬─┘
프로토콜 호스트 포트
같은 출처: 프로토콜 + 호스트 + 포트 모두 동일
URL
동일 출처?
https://example.com/a
같은 출처. 경로만 다르다
http://example.com
다른 출처. 프로토콜이 다르다
https://api.example.com
다른 출처. 호스트가 다르다
https://example.com:8080
다른 출처. 포트가 다르다
왜 필요한가?
[악성 사이트] evil.com
↓ 사용자 브라우저에서
fetch('https://bank.com/transfer')
↓ 쿠키가 자동으로 포함됨!
→ CORS가 없으면 → 돈 이체 성공 😱
→ CORS가 있으면 → 브라우저가 차단 🛡️
동작 흐름
[단순 요청] (GET, 일부 POST)
Browser → Server
Origin: https://app.com
Server → Browser
Access-Control-Allow-Origin: *
→ 허용!
[Preflight 요청] (PUT, DELETE 등)
Browser → Server (OPTIONS)
Origin: https://app.com
Access-Control-Request-Method: PUT
Server → Browser
Access-Control-Allow-Origin: ...
Access-Control-Allow-Methods: PUT
→ OK면 실제 요청 진행
Preflight가 필요한 경우
조건
단순 요청
Preflight
GET, HEAD, POST
해당
PUT, DELETE, PATCH
해당
Content-Type: json
해당
커스텀 헤더
해당
Authorization 헤더
해당
서버 설정 (응답 헤더)
Access-Control-Allow-Origin: https://app.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400
헤더
역할
Allow-Origin
허용할 출처 (* 또는 특정)
Allow-Methods
허용할 HTTP 메서드
Allow-Headers
허용할 커스텀 헤더
Allow-Credentials
쿠키/인증 포함 허용
Max-Age
Preflight 캐시 시간
주의: Credentials + 와일드카드
동시에 쓸 수 없다:
Allow-Origin: *
Allow-Credentials: true
특정 출처를 명시해야 한다:
Allow-Origin: https://app.com
Allow-Credentials: true