ballqs 님의 블로그
[Spring] CORS란? 본문
CORS란 무엇인가?
**CORS(Cross-Origin Resource Sharing)**는 다른 출처 간 리소스 요청을 허용하기 위한 웹 표준입니다. 기본적으로 브라우저는 보안상의 이유로 다른 출처에서의 리소스 접근을 차단합니다. 이를 **동일 출처 정책(Same-Origin Policy)**이라고 하는데, 동일 출처 정책에 의해 자바스크립트로 로드된 리소스가 다른 출처(서버)에 API 요청을 할 경우 브라우저가 이를 막습니다.
여기서 다른 출처란 다음 세 가지 중 하나라도 다를 경우를 의미합니다:
- 도메인 (예: example.com vs. api.example.com)
- 포트 (예: http://localhost:3000 vs. http://localhost:8080)
- 프로토콜 (예: http vs. https)
CORS는 이러한 제한을 완화하여 다른 출처에서의 리소스 요청을 허용하기 위해 사용됩니다.
CORS 작동 방식
- 브라우저 요청: 브라우저는 다른 출처로 리소스를 요청할 때, 그 요청이 CORS 정책에 위배되는지 확인합니다. 만약 위배된다면, 서버로 요청을 보내기 전에 preflight 요청이라고 불리는 OPTIONS 메서드 요청을 보냅니다.
- 서버 응답: 서버는 이 preflight 요청을 받아, 클라이언트가 보내는 실제 요청을 허용할 수 있을지 결정합니다. 이를 위해 서버는 특정 헤더(Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers)를 포함하여 응답을 돌려보냅니다.
- 실제 요청 처리: 만약 서버가 CORS 정책을 준수하면, 브라우저는 이후에 실제 요청을 보낼 수 있고, 그렇지 않다면 브라우저는 요청을 차단합니다.
Spring Boot에서 CORS 설정
Spring Boot에서 CORS를 설정하는 방법은 여러 가지가 있습니다. 전역 설정, 특정 컨트롤러 수준에서의 설정 등 다양한 방법을 지원하며, 아래에서 각각의 방법을 설명합니다.
1. 컨트롤러 레벨에서 CORS 설정
특정 컨트롤러나 메서드에 대해 CORS 설정을 하고 싶다면, @CrossOrigin 애노테이션을 사용할 수 있습니다.
@RestController
@RequestMapping("/api")
public class ExampleController {
@CrossOrigin(origins = "http://localhost:3000") // 특정 출처에서만 허용
@GetMapping("/example")
public String example() {
return "CORS enabled!";
}
}
여기서 @CrossOrigin 애노테이션은 특정 HTTP 메서드 또는 엔드포인트에서 다른 출처의 요청을 허용하는 역할을 합니다.
- origins: 허용할 출처를 설정합니다. 예를 들어 http://localhost:3000에서 오는 요청만 허용하도록 할 수 있습니다.
- allowedMethods: 허용할 HTTP 메서드를 설정할 수 있습니다. (예: GET, POST, PUT, DELETE)
- maxAge: preflight 요청의 유효시간을 설정합니다. 기본값은 1800초(30분)입니다.
2. 전역(Global) CORS 설정
애플리케이션 전체에서 CORS를 적용하고 싶을 때는 WebMvcConfigurer를 구현하여 설정할 수 있습니다.
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("/**") // 모든 경로에 대해 CORS 설정
.allowedOrigins("http://localhost:3000") // 허용할 출처
.allowedMethods("GET", "POST", "PUT", "DELETE") // 허용할 HTTP 메서드
.allowedHeaders("*") // 모든 헤더 허용
.allowCredentials(true) // 쿠키 허용 여부
.maxAge(3600); // preflight 요청 캐싱 시간 (1시간)
}
}
이렇게 하면 애플리케이션의 모든 엔드포인트에서 특정 출처의 요청을 허용하게 됩니다. addMapping("/**")을 통해 모든 경로에 대해 CORS를 적용할 수 있습니다.
3. Spring Security와 함께 CORS 설정
Spring Security가 적용된 애플리케이션에서는 추가적인 CORS 설정이 필요합니다. 보안 필터 체인이 먼저 동작하기 때문에 Security 설정 파일에서 CORS를 허용해야 합니다.
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.cors() // CORS 설정 적용
.and()
.csrf().disable() // CSRF 보호 비활성화 (개발 환경에서만)
.authorizeHttpRequests()
.anyRequest().authenticated();
return http.build();
}
}
여기서 http.cors()를 사용하여 Spring Security에서 CORS 설정을 적용할 수 있으며, WebMvcConfigurer와 함께 사용해야 합니다.
4. 프로그래밍적으로 CORS 설정 추가
특정 상황에서 Filter를 사용해 CORS 설정을 직접 커스터마이징할 수도 있습니다.
import org.springframework.stereotype.Component;
import javax.servlet.FilterChain;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class SimpleCorsFilter implements Filter {
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
response.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Max-Age", "3600");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) {}
@Override
public void destroy() {}
}
CORS 설정 시 주의할 점
- 보안:
- Access-Control-Allow-Origin을 특정 출처로 제한하는 것이 중요합니다. *로 설정하여 모든 출처를 허용하는 것은 보안상 좋지 않습니다.
- allowCredentials(true)로 설정하면 쿠키나 인증 정보를 포함한 요청을 허용할 수 있으므로, 신중하게 설정해야 합니다.
- preflight 요청:
- OPTIONS 메서드를 사용한 preflight 요청은 서버에 추가적인 부하를 줄 수 있습니다. 필요에 따라 maxAge 값을 늘려 캐싱을 고려해보는 것이 좋습니다.
- API 버전별 설정:
- 만약 여러 버전의 API를 운영한다면, 각각의 버전에 대해 별도로 CORS 정책을 설정할 수 있습니다. 예를 들어 api/v1, api/v2 등의 경로에 대해 다르게 설정할 수 있습니다.
'코딩 공부 > Spring' 카테고리의 다른 글
[Spring] @Mock , @MockBean 의 차이점 (0) | 2024.09.14 |
---|---|
[Spring] @Configuration 란? (0) | 2024.09.14 |
[Spring] 테스트 코드 심화(Controller , Service) (0) | 2024.09.11 |
[Spring] AOP 동작 흐름 및 패턴 이해 (0) | 2024.09.10 |
[Spring] Redis 적용 (Window 환경) (0) | 2024.09.08 |