아래 환경에서 개발하다가 로그인 기능을 테스트하는 단계에서 발생한 오류입니다.
Front-End : React (axios 사용) 3000번 포트 서비스
Back-End : Java / Spring 8888 포트 서비스
위 에러가 발생한 원인은 웹 상에 존재하는 "동일 출처 정책" 이라는 보안 정책에 위배되는 요청을 보냈기 때문입니다.
아래는 동일 출처 정책에 대한 설명입니다.
동일 출처 정책(same-origin policy)은 어떤 출처에서 불러온 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한하는 중요한 보안 방식입니다. 동일 출처 정책은 잠재적으로 해로울 수 있는 문서를 분리함으로써 공격받을 수 있는 경로를 줄여줍니다.
출처 : https://developer.mozilla.org/ko/docs/Web/Security/Same-origin_policy
https://developer.mozilla.org/ko/docs/Web/Security/Same-origin_policy
즉, 문서나 스크립트 등의 리소스가 "다른 출처" 에서 발생한 요청이 경우, 이를 신뢰할 수 없어 차단하는 정책이라는 의미인데....
좀 더 백엔드 개발에 접목해서 이야기 하자면 아래와 같은 경우를 말합니다.
프론트 엔드 서버에서 백엔드 서버로 요청을 보내는 과정을 표현하자면 아래와 같이 표현할 수 있습니다.
프론트엔드는 ReactJs 로 구현되어 있고, 백엔드는 Java/Spring 으로 구현되어 있습니다.
프론트엔드에서 백엔드로 REST API를 호출하여 응답을 json으로 내려받아 화면에 데이터를 랜더링하는 방식으로 되어있습니다.
여기서 문제가 뭘까요?
바로, 백엔드를 서비스하는 URL(http://localhost:8888)과 프론트엔트를 서비스하는 URL(http://localhost:3000)이 다르다는 점입니다.
앞서 설명한 "동일 출처 정책" 에 의해 백엔드 서비스에선 자신과 동일한 URL로 들어온 요청만을 받아들이고, 다른 URL은 보안상 문제로 요청을 허용하지 않습니다.
그렇기 때문에, 백엔드 서비스에서 "어? 이건 내가 신뢰할 수 없는 URL인데? 접근을 불허한다!" 하고 오류를 뱉는 것 입니다.
저 같은 경우에는 Spring 설정을 추가하여 해당 문제를 해결했습니다. 그 설정은 아래와 같습니다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
private static final String[] WHITE_LIST = {
"http://localhost:3000"
};
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(WHITE_LIST)
.allowedMethods(
HttpMethod.GET.name(),
HttpMethod.POST.name(),
HttpMethod.PUT.name(),
HttpMethod.DELETE.name()
);
}
}
@Configuration 어노테이션을 통해, SpringApplication 을 실행할 때, 아래 class 설정을 적용하도록 했습니다.
WebConfig class 는 Spring 에서 지원하는 WebMvcConfigurer 를 상속받고, 수 많은 메서드 중 "addCorsMappings" 메서드를 재정의 했습니다.
해당 메서드에서는
- addMapping : 어떤 URI 에 대해 설정을 적용할 것 인가 (/** 는 모든 URI 에 적용한다는 의미)
- allowedOrigins : 어느 요청에 대해 적용할 것인가 (상단에 정의된 WHITE_LIST 배열에 선언된 URL은 허용하겠다는 의미)
- allowedMethods : 어떤 HttpMethod 에 대해 적용할 것인가 (GET, POST, PUT, DELETE 메서드에만 적용하겠다는 의미)
를 적용했습니다.
위에서 적용한 3개의 옵션 말고도 많은 옵션을 정의할 수 있습니다. (하지만, 전 간단하게 꼭 필요한 3개만 해봤습니다.)
기타 추가적인 설명은 아래 Spring 공식 문서를 참고해주세요.
https://docs.spring.io/spring-framework/reference/web/webmvc-cors.html
댓글