CORS 해결 패턴

CORS 헤더는 브라우저 노출, 인증정보, 캐시 키를 함께 맞춰야 한다

Allow-Origin만 맞추면 끝나는 문제가 아니다. credentials 요청, 커스텀 헤더, Origin 반사, Vary 캐시 키가 같이 맞아야 운영 오류가 줄어든다.

CORS 요청과 응답 헤더 흐름 브라우저가 Origin과 preflight 정보를 보내고 API가 Allow-Origin, Credentials, Vary를 맞춰 응답해야 자바스크립트에 노출된다. Browser Origin 포함 요청 Preflight OPTIONS / headers Actual request fetch credentials API / CDN 허용 목록 검증 Shared cache Vary: Origin 필요 Allow-Origin Credentials Vary: Origin 쿠키 요청에서는 * 대신 정확한 Origin을 반환
Browser Origin, preflight 여부, credentials 설정을 요청에 싣는다.
01 request
Origin을 기준으로 허용 여부를 묻는다 scheme, host, port 조합이 CORS 판단의 출발점이다.
02 allow
Allow-Origin은 정확한 출처를 반사한다 쿠키 요청에서는 * 대신 허용 목록의 Origin을 반환한다.
03 credential
쿠키 포함 요청은 별도 허가가 필요하다 Allow-Credentials와 fetch credentials 설정을 함께 맞춘다.
04 cache
공유 캐시는 Origin별 응답을 섞지 않는다 동적 Origin 반사면 Vary: Origin으로 캐시 키를 분리한다.
경고
CORS는 CSRF 방어가 아니다 토큰, SameSite, Origin 검증은 별도 보안 정책으로 둔다.
API Server / CDN 보안 규칙은 서버가 판정하고, 캐시 정책은 헤더로 고정한다.

Browser

요청은 보낼 수 있지만 JavaScript에 응답을 노출할지는 CORS 헤더로 결정한다.

Origin

요청 출처를 서버에 전달

https://app.example처럼 scheme, host, port 조합이 기준이다.

Allow-Origin

허용 목록 검증 뒤 정확한 Origin 반환

허용하지 않은 Origin은 헤더를 생략하거나 거부 응답으로 처리한다.

Credentials

쿠키 포함 요청은 특정 Origin만 허용

Allow-Credentials: truecredentials: include가 함께 필요하다.

Vary: Origin

공유 캐시가 다른 Origin 응답을 섞지 않게 한다

Origin별로 Allow-Origin이 달라지면 캐시 키에도 Origin이 들어가야 한다.

API Server / CDN

브라우저 보안 규칙을 이해하고, 서버 정책을 헤더로 명확히 표현한다.

Allow-Headers

요청 커스텀 헤더 허용

Authorization, Content-Type 같은 preflight 요청 헤더 이름을 확인한다.

Expose-Headers

JS가 읽을 응답 헤더 노출

X-Request-Id 같은 응답 헤더를 프론트에서 읽으려면 명시해야 한다.

Max-Age

preflight 결과 캐시

반복 OPTIONS를 줄이되 브라우저별 상한과 정책 변경 지연을 고려한다.

CSRF

CORS는 CSRF 방어가 아니다

요청 자체는 전송될 수 있으므로 토큰, SameSite, Origin 검증을 따로 둔다.

개발 환경 우회와 운영 정책을 섞지 않는다

개발 중에는 dev server proxy가 편하지만, 운영에서는 서버가 허용 Origin, credentials, headers, Vary를 명확히 응답해야 한다. Origin을 무조건 반사하는 코드는 테스트에서는 편해도 공유 캐시와 쿠키 요청에서 위험하다.