본문 바로가기
WEB/Spring

Spring Boot CORS 사용 목적과 브라우저 보안 SOP

by 정권이 내 2025. 6. 4.

Spring Boot CORS

 

CORS(Cross Origin Resource Sharing) 는 프론트와 백엔드가 분리된 요즘 웹환경에서 필수로 이해해야 하는 개념입니다.

 

CORS란?

CORS는 다른 도메인간의 HTTP 요청을 허용할지 말지를 서버가 명시적으로 제어할수 있게 해주는 보안 정책입니다.

 

위와 같은 설정에서 도메인/포트가 다르면 크로스 오리진 요청 으로 간주되며 브라우저는 보안상 기본적으로 이 요청을 차단합니다. 서버에서 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

 

OriginSOP 위반
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에서 읽지 못하도록 막는것입니다.

브라우저 내부 흐름

  1. 브라우저에서 요청 전송
  2. 서버에서 응답 받음
  3. [서버] Access-Control-Allow-Origin 헤더 없음 판단
  4. [서버] JS에 응답 전달 ❌
  5. 브라우저에서 에러

 

브라우저의 콘솔에서는 다음과 같은 에러 로그가 출력됩니다.

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 설정을 하지않으면 브라우저에서 에러가 발생합니다.

  1. React → fetch("http://localhost:8080/api/data")
  2. 브라우저 → CORS 요청 → Spring Boot서버
  3. Spring Boot 서버 → CORS 허용 여부 응답
  4. 브라우저가 최종 요청 수행

 

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);
    }
}

 

정리

개념설명
SOPJavaScript는 같은 출처에서만 요청/응답 가능
CORSSOP 예외를 허용하기 위한 서버 측 설정 방식
never.com → naver.com 요청가능은 하지만 응답을 읽지 못함 (브라우저가 차단)
보안 효과세션 탈취, 민감 정보 조회 등 공격 방지
반응형

댓글