꼭 필요하지만 가끔은 귀찮은 CORS 정리

프론트엔드스프링
By Jeongmin Seo4월 20일, 2025년

목차

    CORS (Cross-Origin Resource Sharing)

    대부분의 개발자는 외부 API를 연동하면서 CORS 문제를 한 번쯤 겪어봤을 것이다.
    CORS는 브라우저가 다른 출처(origin)의 자원에 접근할 때 보안을 위해 서버에 요청 권한을 묻는 정책이다. 동일 출처가 아닌 요청은 기본적으로 차단된다.


    동일 출처(origin)란?

    동일 출처란 아래 세 가지가 모두 같아야 한다:

    • 프로토콜 (http, https)
    • 도메인 (정민.xyz, google.com)
    • 포트 (80, 443 등)

    https://정민.xyz 기준 예시:

    요청 URL동일 출처 여부
    https://정민.xyz/api동일
    http://정민.xyz/api다른 프로토콜
    http://api.정민.xyz다른 서브도메인
    http://정민.xyz:3000다른 포트

    CORS 동작 방식

    1. 클라이언트에서 다른 origin으로 요청을 보낸다.
    2. 브라우저는 Preflight 요청을 먼저 보낸다.
      • OPTIONS 메서드로 서버에 “이 요청 허용되나요?”를 묻는다.
    3. 서버는 Access-Control-Allow-* 헤더를 포함하여 응답한다.
    4. 브라우저가 허용되었다고 판단하면 실제 요청을 진행한다.

    모든 요청이 Preflight 요청을 거치는 것은 아니다. 단순 GET 요청 등은 생략될 수 있다.


    주요 응답 헤더

    • Access-Control-Allow-Origin: 허용된 출처 (ex: https://example.com 또는 *)
    • Access-Control-Allow-Methods: 허용된 HTTP 메서드 (ex: GET, POST, PUT)
    • Access-Control-Allow-Headers: 허용된 헤더 목록 (ex: Content-Type, Authorization)
    • Access-Control-Allow-Credentials: 인증 정보 포함 허용 여부 (true/false)

    예시

    OPTIONS /api HTTP/1.1 Origin: https://정민.xyz Access-Control-Request-Method: POST Access-Control-Request-Headers: Content-Type
    HTTP/1.1 200 OK Access-Control-Allow-Origin: https://정민.xyz Access-Control-Allow-Methods: GET, POST Access-Control-Allow-Headers: Content-Type

    이후 실제 POST 요청이 정상적으로 진행된다.


    Spring 기준 CORS 해결법

    1. 컨트롤러 단위 설정 (@CrossOrigin)

    @RestController @RequestMapping("/api") @CrossOrigin(origins = "http://localhost:3000") // 허용할 프론트엔드 주소 public class MyController { @GetMapping("/data") public String getData() { return "Hello CORS"; } }
    • 특정 컨트롤러 또는 메서드에만 적용 가능
    • origins, methods, allowedHeaders 등 옵션 설정 가능

    2. 글로벌 설정 (Spring WebMvcConfigurer)

    @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 모든 경로 허용 .allowedOrigins("http://localhost:3000") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowedHeaders("*") .allowCredentials(true); } }
    • 모든 요청에 대해 글로벌 CORS 설정 가능
    • 프로젝트 규모가 크거나 여러 컨트롤러에서 공통으로 적용할 때 유용

    마무리

    CORS는 브라우저 보안을 위해 반드시 필요하지만, 외부 API 연동 시 자주 문제를 발생시키는 요소다. Spring에서는 @CrossOrigin 또는 글로벌 설정을 통해 쉽게 문제를 해결할 수 있다.