[CORS] Preflight OPTIONS 요청 분석

이지연·2026년 1월 26일

네트워크

목록 보기
5/6

CORS와 Preflight OPTIONS 요청

CORS(Cross-Origin Resource Sharing)는 브라우저의 동일 출처 정책(Same-Origin Policy)을 우회해 다른 출처 리소스 접근을 허용하는 표준 메커니즘이다.

1. 동일 출처 정책

같은 출처 = 프로토콜 + 도메인 + 포트 동일
✅ http://localhost:8080 → http://localhost:8080
❌ http://localhost:3000 → http://localhost:8080 (다른 출처)
❌ https://api.example.com → http://localhost:8080 (다른 출처)

브라우저는 다른 출처 요청을 기본 차단 → CSRF 등 보안 공격 방지.

2. Preflight(OPTIONS) 요청 상세 흐름

다른 출처 POST 요청 시:

[프론트 JS] OPTIONS /api/login (브라우저 자동 사전 확인)
Origin: http://localhost:3000
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Authorization,Content-Type

[서버] 200 OK + 허용 헤더
Access-Control-Allow-Origin: http://localhost:3000 (또는 *)
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
Access-Control-Allow-Headers: Authorization,Content-Type
Access-Control-Max-Age: 1800 (캐싱 30분)
Access-Control-Allow-Credentials: true (토큰/쿠키 허용)

[프론트 JS] POST /api/login (본 요청 진행)
Authorization: Bearer xxx

3. Preflight 필요한 경우

✅ non-simple 요청
- Content-Type: application/json
- custom header (Authorization 등)
- PUT/DELETE/PATCH 메서드

✅ OPTIONS 자동 발생 → 서버 허용 응답 확인 → 본 요청

4. 서버 응답 누락 시 CORS 에러

브라우저 콘솔:
Access to fetch at 'http://api.example.com' 
from origin 'http://localhost:3000' has been blocked by CORS policy

원인:

  • Access-Control-Allow-Origin 없음
  • 요청 메서드/헤더가 허용 목록에 없음

5. Spring Boot CORS 설정 예시

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowedOrigins(Arrays.asList(
        "http://localhost:3000",
        "https://frontend.com"
    ));
    config.setAllowedMethods(Arrays.asList("*"));
    config.setAllowedHeaders(Arrays.asList("*"));
    config.setAllowCredentials(true);
    config.setMaxAge(1800L); // Preflight 캐싱 30분
    
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);
    return source;
}

6. 네트워크 탭 실제 확인

Chrome DevTools → Network
1. OPTIONS /api/login → 200 (Preflight)
2. POST /api/login → 200 (본 요청)

7. 서버↔서버 통신과 차이

✅ 서버 → 서버 요청: CORS 제약 없음 (브라우저 미개입)
❌ 브라우저 → 서버 요청: CORS + Preflight 필수

핵심: 브라우저가 OPTIONS로 서버 정책 확인 → 허용 시에만 본 요청 진행. Spring Security cors() 설정으로 완벽 처리.

profile
Eazy하게

0개의 댓글