Spring Boot CORS
CORS(Cross Origin Resource Sharing) 는 프론트와 백엔드가 분리된 요즘 웹환경에서 필수로 이해해야 하는 개념입니다.
CORS란?
CORS는 다른 도메인간의 HTTP 요청을 허용할지 말지를 서버가 명시적으로 제어할수 있게 해주는 보안 정책입니다.
- 프론트엔드: http://localhost:3000
- 백엔드 : http://localhost:8080
위와 같은 설정에서 도메인/포트가 다르면 크로스 오리진 요청 으로 간주되며 브라우저는 보안상 기본적으로 이 요청을 차단합니다. 서버에서 CORS 허용을 명시해야만 요청이 성공합니다.
이는 허용된 도메인만 접근 가능하게 하는 Access Control List 역할을 수행하는 것입니다.
서버가 Access-Control-Allow-Origin 헤더를 설정하지 않을경우
- 브라우저는 해당 응답을 거부
- 민감한 API나 데이터는 의도한 출처에서만 접근 가능하게 통제 가능
SOP(Same-Origin Policy) 웹 보안의 기본
CORS를 이해하려면 먼저 SOP를 이해해야 합니다. SOP는 어떤 출처(origin) 의 웹페이지가 다른 출처의 리소스에 접근하지 못하도록 차단하는 브라우저의 기본 보안 정책입니다.
여기서 출처(origin) 는 3가지 기준으로 판단합니다. ex) http://naver.com
- 프로토콜 : http / https
- 도메인 : naver.com
- 포트: 8080
Origin | SOP 위반 |
---|---|
http://naver.com:8080 | 정상 |
http://naver.com:3000 | 포트 |
https://naver.com | 프로토콜 |
http://never.com | 도메인 |
예를들어 사용자가 현재 http://naver.com 라는 사이트에 로그인되있는 상태이고 해킹 사이트인 http://never.com 에서 사용자가 접속중인 사이트에 API 요청을 전송한다고 해봅시다.
fetch("http://naver.com:8080/api/user-info", {
credentials: 'include' // 쿠키도 보내려고 함
})
이 JS 코드는 사용자가 로그인한 naver.com에 API 요청을 보내는데 CORS 설정이 없다면 사용자의 민감정보가 노출되거나 계정이 조작될 위험이 발생하게 됩니다. => CRSF(Cross-Site Request Forgery) 공격
핵심은 CORS 설정을 함으로써 공격자의 사이트의 브라우저에서 응답은 받아도 JS에서 읽지 못하도록 막는것입니다.
브라우저 내부 흐름
- 브라우저에서 요청 전송
- 서버에서 응답 받음
- [서버] Access-Control-Allow-Origin 헤더 없음 판단
- [서버] JS에 응답 전달 ❌
- 브라우저에서 에러
브라우저의 콘솔에서는 다음과 같은 에러 로그가 출력됩니다.
Access to fetch at 'http://naver.com:8080/api/user-info' from origin 'http://never.com'
has been blocked by CORS policy.
CORS 필요한 이유
브라우저의 보안정책인 SOP 에 대응하기 위해 서버에서는 올바른 요청에는 응답을 주고 악성 스크립트 등에는 응답을 읽지 못하게 하기 위해 CORS 설정을 해야합니다.
- CORS는 JS에서 응답을 읽지 못하게 할뿐 응답 자체를 차단하는것이 아님
- CORS는 브라우저 기반 보안이며 브라우저가 아닌 Postman 등에는 적용되지 않음
- CRSF 방지와는 직접적 연관은 없지만 CORS + CSRF Token 조합으로 보안 강화 가능
SPA(React, Vue 등의 프론트 엔드) 와 Spring Boot 백엔드 서버가 분리된 구조에서는 CORS 설정을 하지않으면 브라우저에서 에러가 발생합니다.
- React → fetch("http://localhost:8080/api/data")
- 브라우저 → CORS 요청 → Spring Boot서버
- Spring Boot 서버 → CORS 허용 여부 응답
- 브라우저가 최종 요청 수행
Spring Boot는 Spring MVC 위에서 동작하므로 모든 CORS 설정은 DispatcherServlet → HandlerMapping → HandlerInterceptor 흐름 안에서 처리 됩니다.
Spring Boot 에서는 CORS 요청을 감지하면 CorsProcessor 를 통해 CorsConfiguration 에 따라 응답 헤더를 설정 합니다.
CORS 설정 방법
1. 글로벌 설정 (WebMvcConfigurer)
- 전체 API에 대해 공통적으로 CORS를 적용하는 방법입니다.
- 모든 컨트롤러에 대해 자동 적용되므로 일반적인 방식 입니다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 모든 URL에 대해
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true); // 쿠키 포함 허용 시
}
}
allowedOrigins
- http://localhost:3000 에서 온 요청만 허용
- 와일드카드
*
도 가능하지만 allowCredentials(true) 와 함께 쓸수 없음
allowedMethos
- 어떤 HTTP 메서드가 허용되는지 설정
allowedHeader
- 클라이언트에서 어떤 헤더를 포함해서 요청할수 있는지 지정
*
는 모든 헤더를 허용하는 뜻이며 Authorization, Content-Type, X-Requsted-With 등이 있음
allowedCredentials
- true일 경우 쿠키, 인증 정보, 세션, Authorization 헤더 등을 포함한 요청을 허용
- 사용자가 로그인 되어있을 경우 세션 쿠키가 포함되어야 하는 요청등에 필요
2. 컨트롤러, 메서드 레벨 설정
- 특정 API에만 CORS를 적용하고 싶을때 사용됩니다.
- @CrossOrigin 은 클래스나 메서드 단위로 설정 가능합니다.
- 주로 테스트 코드 용도로 사용됩니다.
@RestController
@CrossOrigin(origins = "http://localhost:3000")
public class MyApiController {
@GetMapping("/api/data")
public String getData() {
return "Hello, CORS!";
}
}
3. Filter 기반 수동 설정 (고급 제어)
- Spring Filter Chain 에서 직접 CORS 헤더를 설정할수도 있습니다.
- Spring Security 보다 먼저 필터가 동작하므로 주의가 필요합니다.
@Component
public class CustomCorsFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
response.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
response.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
return;
}
filterChain.doFilter(request, response);
}
}
정리
개념 | 설명 |
---|---|
SOP | JavaScript는 같은 출처에서만 요청/응답 가능 |
CORS | SOP 예외를 허용하기 위한 서버 측 설정 방식 |
never.com → naver.com 요청 | 가능은 하지만 응답을 읽지 못함 (브라우저가 차단) |
보안 효과 | 세션 탈취, 민감 정보 조회 등 공격 방지 |
'WEB > Spring' 카테고리의 다른 글
Spring vs SpringBoot 비교, 차이점 알아보기 (2) | 2025.06.04 |
---|---|
Spring Boot의 HTTP 요청 처리 과정: 필터부터 AOP까지 (0) | 2025.04.16 |
TDD(테스트 주도 개발, Test-Driven Development), Junit (0) | 2024.11.05 |
의존성 주입 애노테이션 @RequiredArgsConstructor, @AllArgsConstructor, @NoArgsConstructor 핵심 정리 (0) | 2024.10.31 |
[Spring] 의존관계 주입(Dependency Injection) 개념과 Bean 중복방지 (0) | 2023.12.14 |
댓글