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

보안을 위해 꼭 필요한 기능이지만, 가끔은 너무나 귀찮게 느껴지는 CORS를 한 번 정리해보자.
프론트엔드스프링
By Jeongmin Seo4월 21일, 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 또는 글로벌 설정을 통해 쉽게 문제를 해결할 수 있다.