SPRING

[Project] CORS 에러 발생, 결국 해결

자몽비앙코 2025. 3. 11. 15:49

우리 프로젝트는 컨트롤러에 CrossOrigin 어노테이션을 박는 방식으로 간단히 postman과 연동해왔는데,

프론트와 백을 연결하는 단계에서 CORS 에러가 발생했다.

인터넷을 찾아보니 이런 오류는 흔하게 일어나는 것 같다.

CORS가 무엇인지는 여러 사이트들을 통해서 알아보았는데, Cross Origin Resource Sharing이라고 한다.

프로토콜, 호스트, 포트 이 세가지를 합쳐서 Origin 인데, 이 셋 중 하나만 달라도 출처가 다르다고 판단한다고 한다. 

 

간단히 내가 생각하기엔 우리의 프론트 포트번호는 3000번, 백 번호는 8000번이어서 두 포트번호가 다르기 때문에 보안정책에 따라  백과 프론트 사이의 이동이 완벽히 자유롭지는 않은 것 같다.

 

자세한 지식은 아래를 읽어보며 참고하였다.

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS

 

교차 출처 리소스 공유 (CORS) - HTTP | MDN

교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 브라우저가 자신의 출처가 아닌 다른 어떤 출처(도메인, 스킴 혹은 포트)로부터 자원을 로딩하는 것을 허용하도록 서버가 허가 해주는 HTTP

developer.mozilla.org

 

 

GET방식에서는 에러가 발생하지 않는데, PUT방식에서는 무조건적으로 에러가 발생함

에러메세지는 아래와 같다.

calendar:1 Access to XMLHttpRequest at 'http://localhost:8080/plandbee/calendar/modimemo/8' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

 

1. 우리팀은 원래 각 컨트롤러 위에 CrossOrigin 어노테이션을 사용해서 아래와 같이 api를 설정했었다.

@CrossOrigin(origins = "*", allowedHeaders= "*", allowCredentials = "true")
public class TodoListController {
...
}

초반에 간단히 이렇게만 설정했는데, 백과 프론트의 연결이 자유롭게 되었었기 때문에 특별히 문제라고 생각하지 않았었다.

origin은 모든 도메인에서의 요청을 허용한다는 의미이고,

allowHeaders는 모든 요청 헤더를 허용한다는 뜻. 즉 Content-Type, Authorization, X-Custom-Header같은 사용자 정의 헤더도 허용된다고 한다.

allowcredentials는 쿠키, 인증정보(session 등)을 포함한 요청을 허용한다는 의미이다.

단, origin="*"과 함께 사용하면 문제가 되고, 특정 도메인을 지정해서 사용해야 한다고 한다.

결론적으로 우리팀은 위 방식으로 cors문제가 해결되었다.

 

2. CORS 관련 전역설정

인터넷과 챗지피티를 참고하여, Config 파일을 만들어서 전역적인 설정을 해보려고 시도하였다.

/config/SecurityConfig.java 에 생성

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .cors().and()            
            .csrf().disable()
            .authorizeRequests()
            .anyRequest().permitAll();

        return http.build();
    }
}

혹은 

import org.springframework.context.annotation.Bean;
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 {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOrigins("http://localhost:3000") // 프론트엔드 주소
                        .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                        .allowCredentials(true)
                        .allowedHeaders("*")
                        .maxAge(3600); // Preflight 캐싱 (1시간)
            }
        };
    }
}

이런식으로, 모든 방식에 대해서 허용될 수 있도록 설정해보았지만....

 

메모 수정이 되지 않았다ㅠㅠ

 

3. 학원 다른 분들에게 문의

쌤과 다른 분들에게 이거 왜 안되냐고 여러모로 하소연.

한 분이 프론트에서 보내는 주소가 잘못되었거나, 자료형이 다르거나 하는 경우에 이런 문제가 발생한다는 얘기를 해주셨다.

음 설마설마했는데, 사실 이게 문제였다...하하

 


결론적으로는 문제를 해결하긴 했는데, 정석 CORS문제는 아니었고 오타 문제였다는 함정...^^

주소에 d가 추가되어 있어서 어떤 전역적 설정도 불가능한 것이었다.

며칠 전에 거의 3시간동안 이것만 잡고 해보았는데 안되었어서 너무 절망적인 생각이 들었는데,

또 이렇게 해결하고나면 속이 시원해진다.ㅎㅎ

 

<개발자도구, network의 response headers창을 찾아 캡쳐해보자>