728x90
개요
Spring Boot를 사용하며 DELETE 요청에서만 CORS(Cross-Origin Resource Sharing) 문제가 발생하는 경우가 있다.
이번 글에서는 CORS의 기본 개념부터 Spring Boot에서 DELETE 요청과 관련된 문제를 해결하는 방법을 작성했다.
CORS ?
CORS는 브라우저가 다른 도메인의 리소스에 접근할 때 보안을 위해 요청을 제한하는 정책이다.
예를 들어, 클라이언트 애플리케이션이 http://localhost:3000에서 실행 중인데, API 서버가 http://localhost:8080에 있다면, 기본적으로 브라우저는 이를 다른 서버로 간주한다.
CORS 문제는 요청 헤더, 메서드, 또는 인증 정보가 예상과 다를 때 주로 발생한다.
DELETE 요청에서 CORS 문제가 발생하는 이유
DELETE 요청은 브라우저에서 Preflight Request를 통해 서버의 허가를 먼저 요청한다.
이 Preflight Request는 OPTIONS 메서드를 사용하며, 서버는 특정 헤더를 포함한 응답으로 이를 허가해야 한다.
DELETE 요청에서 문제가 발생하는 이유는 주로 아래와 같다.
- 서버가 OPTIONS 요청을 허용하지 않음.
- DELETE 메서드가 CORS 설정에서 누락됨.
- 클라이언트와 서버 간의 헤더 불일치.
문제해결
방법 1
Spring Boot의 @CrossOrigin 사용
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://localhost:3000")
public class ExampleController {
@DeleteMapping("/delete/resource")
public void deleteResource() {
// 로직
}
}
- 장점: 간단하고 특정 엔드포인트에만 CORS를 적용할 수 있음.
- 단점: 엔드포인트가 많아지면 관리가 번거로움.
방법 2
전역 CORS 설정
Spring Security 설정이나 WebMvcConfigurer를 사용하여 프로젝트 전체에 적용되는 CORS 설정을 정의한다.
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 모든 경로에 대해
.allowedOrigins("http://localhost:3000") // 허용할 출처
.allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS") // 허용할 HTTP 메서드
.allowedHeaders("*") // 모든 헤더 허용
.allowCredentials(true); // 인증 정보 허용
}
}
- 장점: 중앙에서 CORS 설정을 관리할 수 있음.
- 단점: 세분화된 설정이 필요할 경우 복잡해질 수 있음.
방법 3
Spring Security를 사용하는 경우
Spring Security가 활성화된 경우, 추가적으로 CORS 설정을 구성해야 한다.
Spring Security의 기본 설정은 CORS를 차단하기 때문이다.
// SecurityConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
return http.build();
}
}
// CorsFilter.java
import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("http://localhost:3000");
config.addAllowedMethod("*");
config.addAllowedHeader("*");
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
문의사항이나 피드백은 댓글로 남겨주세요.
'프로그래밍 언어 > JAVA, SPRING' 카테고리의 다른 글
[SPRING BOOT] 멀티모듈 프로젝트 설계하기 (1) | 2024.11.26 |
---|---|
[SPRING BOOT] WebSocket과 Redis를 활용한 실시간 채팅 시스템 구축하기 (0) | 2024.11.26 |
[SPRING BOOT] UnrecognizedPropertyException 해결하기 (0) | 2024.11.26 |
[JAVA] Exception Handling (0) | 2024.07.22 |
[SPRING] Sleuth (0) | 2024.07.22 |