PreFlightCorsConfig example
@Configuration
public class PreFlightCorsConfig {
private final CorsProperties corsProperties;
public PreFlightCorsConfig(CorsProperties corsProperties) {
this.corsProperties = corsProperties;
}
private static final String ALLOWED_HEADERS = "x-requested-with,authorization, refresh-token,Access-Control-Allow-Origin,Content-Type, credential,X-AUTH-TOKEN,X-CSRF-TOKEN";
private static final String ALLOWED_METHODS = "GET, PUT, POST, PATCH, DELETE, OPTIONS";
private static final String ALLOWED_CREDENTIALS = "true";
// 중요 해당 헤더가 없다면 axios를 통한 프론트에서 확인이 불가능함
private static final String EXPOSE_HEADERS = "*,Authorization,Refresh-token,authorization,refresh-token";
private static final String MAX_AGE = "3600";
@Bean
public WebFilter corsFilter() {
return (ServerWebExchange ctx, WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
String requestOrigin = request.getHeaders().getOrigin();
if (CorsUtils.isPreFlightRequest(request)) {
ServerHttpResponse response = ctx.getResponse();
HttpHeaders headers = response.getHeaders();
if (requestOrigin != null && corsProperties.getAllowedOrigins().contains(requestOrigin)) {
headers.add("Access-Control-Allow-Origin", requestOrigin);
}
headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
headers.add("Access-Control-Max-Age", MAX_AGE);
headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
headers.add("Access-Control-Allow-Credentials", ALLOWED_CREDENTIALS);
headers.add("Access-Control-Expose-Headers", EXPOSE_HEADERS);
// 프론트에서 해당 헤더를 확인할수잇게 허가해줌
headers.add("Access-Control-Expose-Headers", EXPOSE_HEADERS);
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter(ctx);
};
}
}
CorsProperties
@Component
@Getter
@Setter
@ConfigurationProperties(prefix = "app.cors")
public class CorsProperties {
private List<String> allowedOrigins = new ArrayList<>();
}
설정
- dev, prod profile 별로 다르게 설정하는 게 일반적
# application-dev.yml
cors:
allowed-origins:
- "http://localhost:3000"
- "http://127.0.0.1:3000"
# application-prod.yml
cors:
allowed-origins:
- "https://example.com"
- "https://another-domain.com"
spspring-cloud-starter-gateway 사용시
Spring Cloud Gateway를 사용하고 있다면 PreFlightCorsConfig 같은 별도의 Java Config 없이도 application.yml에 설정만으로 CORS 처리가 가능합니다.**
✅ TL;DR
✔️ spring.cloud.gateway.globalcors.cors-configurations
이 설정은 Spring Cloud Gateway 전용이며, Gateway 레벨에서 전역적으로 CORS 프리플라이트 요청을 처리합니다.
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins:
- "https://dev.pink-spider.io"
allowedMethods:
- GET
- POST
- OPTIONS
- PUT
- DELETE
allowedHeaders:
- "*"
exposedHeaders:
- "Authorization"
- "Refresh-token"
allowCredentials: true
allowedHeaders: "*"와 같이 와일드카드도 가능합니다 (필요 시 명시적으로 지정 가능).
✅ 언제 PreFlightCorsConfig가 필요한가?
| 상황 | 필요 여부 |
|---|---|
| Spring Cloud Gateway 사용 | ❌ 필요 없음 (YAML 설정으로 충분) |
| Spring WebFlux/Web MVC 단독 서버 | ✅ 필요 (Filter 또는 WebMvcConfigurer 필요) |
| 특정 조건 하에서 커스텀 로직이 필요한 경우 | ✅ 필요할 수 있음 (예: 다이내믹 Origin 체크 등) |
🎯 정리
- Spring Cloud Gateway를 쓰고 있고, YAML 설정만으로 잘 작동 중이라면
PreFlightCorsConfig는 제거해도 됩니다. - 단, 프리플라이트 요청이 제대로 처리되지 않거나, 동적으로 origin을 제어해야 할 필요가 있을 때만 Java 코드 수준에서 커스터마이징이 필요합니다.