-
[Spring] 리액트(React) - 스프링(Spring) 연동 시 발생하는 CORS 이슈 해결하기Backend Dev/Spring Framework 2023. 3. 5. 15:59728x90
웹 개발 팀 프로젝트를 진행하다 퍼블리싱과 API 개발을 마친 뒤 프론트엔드 쪽에서 API 테스트 도중 다음과 같은 CORS 에러가 발생하였다.
"Access to XmlHttpRequest at A from origin B has been blocked by CORS policy : Response to preflight requeset doesn't pass access control check: No "Access-Control-Allow-Origin" header is persent on the requested resource"
이는 자바스크립트에서 서로 다른 도메인 소스에 대해 ajax 요청 API 호출 시 웹 브라우저가 하나의 서버 연결만 허용하도록 설정되어 있기에 발생하는 에러이다.
CORS(Cross-Orign Resource Sharing) 는 교차 출처 리소스 공유 정책이라는 의미로 교차 출처는 서로 다른 도메인이라는 것과 비슷한 맥락이다. 발생한 에러 문구를 보면 A에서 B라는 출처로 가져올 수 있는 접근이 CORS 정책에 의해 차단되었다는 것을 알려주고, 요청된 리소스에 "Access-Control-Allow-Origin" 헤더가 없다고 한다.
출처는 무엇이고, 브라우저에서는 어떻게 적용되는가?
이를 해결하기 전에 출처에 대해 구체적으로 살펴보면 URL에서 Protocol, Host, Port 까지 합쳐진 걸 말한다. 이 3가지 요소가 동일하면 같은 출처이다. 예를 들어 네이버의 출처는 다음과 같다.
https://www.google.com:443
다른 출처로부터 리소스를 가져오는 것을 차단하는 이유는 보안상 CSRF나 XSS와 같이 악의적으로 접근할 수 있기때문에 브라우저에서 동일한 출처에서만 리소스를 공유할 수 있도록 적용(Same-Origin Policy)되어 있는 것이다. 결국 서버의 문제가 아닌 브라우저 정책에 의해 차단당하는 것이므로 서버-서버 간 다른 출처의 서버로 API를 요청할 시 CORS 에러는 발생하지 않으며 클라이언트 단에서 요청할 때만 발생할 수 있는 에러이다.
그러나, 다른 출처에 있는 리소스를 가져오는 경우는 어떤 웹 애플리케이션에서 사용하든 매우 흔한 일이기에 브라우저는 CORS 정책이 적용되어 특정 리소스에 대해 정책에 속한 규칙에 해당됐을 때는 허용한다. 결론적으로 동일 출처 정책을 위반하여도 CORS 에 의하여 조항만 지켜진다면 다른 출처 리소스도 사용할 수 있음을 의미하는 것이다. 그렇다면 이번에 발생한 CORS 에러를 바탕으로 어떤 규칙에 위반됐으며 어떻게 해결할 수 있었는지 공유하려 한다.
CORS 이슈를 해결하는 방법은 무엇인가?
위 에러에서 보았듯 "Access-Control-Allow-Origin" 헤더가 없다고 하였는데 클라이언트에서 API 요청시 HTTP 헤더에 담긴 Origin과 서버 응답 헤더에 포함된 Access-Control-Allow-Origin 을 비교해서 유효성 검증을 했을 때 일치하지 않는 경우라 발생한 문제이다.
에러 문구에서의 origin은 소셜 로그인 API 요청시 localhost:5173 이었고 서버쪽에서 이 origin의 자원을 사용할 수 있도록 설정해주어야 한다. 필자의 경우 본 프로젝트에서 Spring Framework을 사용하여 Access-Control-Allow-Origin 헤더를 설정해서 출처를 허용하게 하였다.
스프링 시큐리티 설정에서 CorsConfigurationSource를 Bean 등록하여 설정하는 방법과 설정 클래스를 새로 만들어 WebMvcConfigurer의 addCorsMappings를 오버라이딩 하는 방법이 있는데 전자의 경우 올바르게 적용되지 않는 문제가 발생해 후자의 코드를 적용하였다.
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:5173") .allowedMethods("OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE"); } }
전역적으로 CORS를 설정할 수 있는 방법이며 에러에서 허용되지 않았던 http://localhost:5173 Origin을 설정해주었고 이외 사용될 HTTP Method들을 작성해서 세팅 후 재배포하여 다시 테스트를 요청드리고 성공적으로 Cors 이슈를 해결할 수 있었다.
팀 프로젝트 진행 시 프론트엔드 - 백엔드 연동 과정 중에 자주 발생할 수 있는 에러인만큼 재차 기억해두면 많은 도움이 될 것 같다.
728x90'Backend Dev > Spring Framework' 카테고리의 다른 글
[Spring] JPA vs JDBC (0) 2022.12.20 [Spring] 빈 생명주기 콜백 (0) 2022.03.19 [Spring] 동일 타입 빈 조회 (0) 2022.03.16 [Spring] 의존 관계 주입의 다양한 방식 (0) 2022.03.16 [Spring] 컴포넌트 스캔과 의존관계 자동 주입 (0) 2022.03.15