Spring

Spring 에서 CORS 설정

Chan Dev 2025. 7. 9. 21:49

 

 

CORS 란?

Cross-Origin Resource Sharing 의 줄임말로 웹 브라우저에서 다른 출처의 리소스 공유에 대한 허용/비허용을 다룬 보안 정책입니다.

예를 들어, 다른 회사의 API 등 다른 도메인의 API(다른출처) 를 이용하고 싶을 때 CORS 허용 설정이 되어 있어야 성공적으로 API 에 접근해 리소스를 공유받을 수 있습니다.

CORS 설정방법

CORS 에러를 해결하기 위한 여러 방법이 있습니다.

 

WebMvcConfigurer 을 이용해 Spring 서버 전역적으로 설정

Spring 서버에 전역적으로 CORS 설정을 해주기 위해서는 아래와 같이 Configuration 어노테이션을 붙인 스프링 설정 클래스를 생성해주어야 합니다.

// Spring 서버 전역적으로 CORS 설정
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*") // 허용할 출처 : 특정 도메인만 받을 수 있음
                .allowedMethods("GET", "POST") // 허용할 HTTP method
                .allowCredentials(true); // 쿠키 인증 요청 허용
    }
}

 

하지만 이렇게 구현하고 실행하면 에러가 발생합니다. ( 제가 겪은 문제입니다. )

java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.
	at org.springframework.web.cors.CorsConfiguration.validateAllowCredentials(CorsConfiguration.java:473) ~[spring-web-5.3.27.jar:5.3.27]
	at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:532) ~[spring-webmvc-5.3.27.jar:5.3.27]
	...

 

이러한 이유는 Spring Boot 에서 CORS 설정 시 allowedOrigins("*") 와 allowCredentials(true) 를 동시에 사용할 수 없도록 업데이트 되었기 때문입니다.

 

따라서 아래와 같은 코드로 바꾸어 주면 해결이 됩니다.

// Spring 서버 전역적으로 CORS 설정
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*") // “*“같은 와일드카드를 사용
                .allowedMethods("GET", "POST") // 허용할 HTTP method
                .allowCredentials(true) // 쿠키 인증 요청 허용
                .maxAge(3600); // 사전 요청 시간 설정
    }
}

 

여기서 maxAge 는 어떤 기능을 하는가? 라는 의문점이 생길 수 있습니다.

브라우저는 민감한 요청(PUT, DELETE 등) 을 보내기 전에 "이거 진짜 보내도 돼요?" 하고 서버에게 먼저 사전요청(Preflight Request) 을 보냅니다. 이 요청은 OPTIONS 메서드로 보내지게 됩니다.

maxAge 은 이 Preflight 응답을 브라우저가 얼마나 오랫동안 캐싱해둘지를 설정하는 것입니다.

maxAge 를 설정하지 않으면, 브라우저는 매 요청마다 OPTIONS 사전 요청을 보내게 되고 자주 보내게 되면 네트워크 부하가 높아질 수 있습니다. 하지만 maxAge 를 설정하면, 그 시간동안 요청에 대한 정보를 기억하고 있어 네트워크 부하를 줄여줄 수 있습니다.

하지만 너무 길게 설정하면 보안상 위험할 수도 있습니다.

 

Controller 설정

아래와 같은 코드를 사용하면 특정 컨트롤러에 맞는 CORS 를 설정해 줄 수 있습니다.

@RequestMapping("/articles")
@CrossOrigin(origins = "*", allowedHeaders = "*")
public class ArticleController {
	...
}

 

Method 설정

아래와 같이 사용하면 특정 메서드에 CORS 를 적용하실 수 있습니다.

@RestController
@RequestMapping("/articles")
public class ArticleController {

    @CrossOrigin(origins="*")
    @DeleteMapping(value = "/{articleId}")
    public ResponseEntity<ArticleResponseDto> delete(@PathVariable Long articleId) throws Exception{
    	...
    }

}

 

테스트해보기

React, Spring Boot를 이용해서 간단한 테스트를 진행했습니다.

아래는 테스트한 코드와 결과 입니다.

 

Spring Boot ( 만약 CORS 를 해결하지 않았다면 )

 

이렇게 브라우저에서 Access-Control-Allow-Origin 에러가 발생하는 모습을 볼 수 있습니다.

 

하지만 WebConfig.java 에서 CORS 를 해결하면 아래와 같이 데이터를 잘 불러올 수 있습니다.