프로그래밍/spring

CORS error 발생! 그게 뭔데?

승민아 2024. 8. 14. 15:57

이전에 잘만 서버에서 처리하던 업로드 요청이...

도메인을 구입하여 서버와 연결한 이후에

파일 업로드 기능을 수행했더니 ... 다음과 같은 상황이 발생했다.

CORS, preflight

빨간색으로 에러가 팡팡~ 서버에서 처리하지 못하는 에러는 아니다.

CORS error, preflight 그게 뭔데~~!

 

OPTIONS 메서드?

OPTIONS 메서드는 뭔데~~!

 

출처에 따른 리소스 공유

브라우저는 SOP(Standard Operating Procedures) 정책을 따른다.

그 정책중에 "같은 출처에서만 리소스를 공유할 수 있다"가 있다.

 

출처에 따른 리소스 공유가 무엇일까? 

출처 : https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

 

내가 만든 웹이 a.com이라고하자.

a.com에서 업로드된 이미지 파일을 가져오기위해서 a.com에 이미지 파일을 요청할 수 있다.

이때 a.com에서 a.com으로 요청을 했다. 이것이 같은 출처에게 리소스를 공유하는 상황이다.

 

내가 만든 웹이 a.com인데

이 웹에서 이미지 파일을 가져오기위해 b.com에 요청할 수 있다.

이때 a.com에서 b.com으로 요청했다. 다른 출처를 가지는 리소스를 공유하는 상황이다.

이것은 기본 COP 정책을 위반하는것이다.

 

CORS ?

CORS는 Cross-Origin Resource Sharing이다.

"교차 출처 리소스 공유" 다른 출처끼리 리소스를 공유하는 것이다. 

클라이언트 애플리케이션은 공격을 받기도 하기도 쉬운 환경이기 때문에 CORS 정책이 필요한 것이다.

 

OPTIONS, Preflight ?

CORS 시나리오에는 Simple Request, Preflight Request, Credential Request 3가지가 존재한다.

 

Simple Request는 특정 조건을 만족하는 경우

서로 다른 출처라도 CORS 정책 검사를 하지 않고, 예비 요청을 생략할 수 있는 경우이다.

 

현재 내가 발생한 문제는 Preflight Request에서 발생한 문제라서 이 경우만 다뤄보자.

 

Preflight Request 경우에 한번에 본 요청을 보내지 않고, 예비 요청을 먼저 보낸다.

이 예비 요청을 Preflight라고 부르며 OPTIONS 메서드를 사용한다.

예비 요청을 통해서 브라우저가 이 요청을 보내는것이 안전한지 확인하는 단계이다.

 

HOST와 Origin

http://13.123.123.12:8080/posters/image

"http://"는 Protocol

"13.123.123.12:8080"는 Host

"/posters/image"는 path이다.

 

Host는 내가 요청을 보내는 대상이고,

Origin은 요청이 시작하는곳이 된다. 위의 표현에서 "내가"되는것이다.

 

문제 원인 및 해결 방법

서버에 이미지 파일을 보내는 자바 스크립트 코드의 일부분이다.

const xhr = this.xhr = new XMLHttpRequest();
xhr.open('POST', 'http://13.123.123.12:8080/posters/image', true);

 

URL이 "http://13.123.123.12:8080/"으로 요청을 보내는 대상인 HOST가 "13.123.123.12:8080"으로 되어있다.

 

웹 브라우저는 기본적으로 같은 출처의 리소스만 허용하기 때문에

도메인을 등록한 이후 a.com으로 접속했기 때문에 요청이 시작하는 출처인 Origin이 a.com인데

요청을 보내는 대상인 HOST가 "13.123.123.12:8080"이기 때문에

달라서 CORS 에러가 발생하는 것이다.

 

즉, HOST는 13.123.123.12:8080인데 Origindms a.com이라 CORS 발생한것이다.

 

만약 다른곳에서 API를 사용하지 않는 상황이고 자신의 사이트에서만 사용한다면

간단하게 다음과 같이 HOST를 Origin으로 맞춰주면 에러는 해결할 수 있다.

Host를 Origin과 맞춰주자

 

만약 세세하게 Cors 정책을 설정하고싶다면 다음과 같이 CorsFilter를 빈으로 등록해주자.

@Configuration
public class CorsConfig  {

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true); // 내 서버가 응답할때 json을 자바스크립트에서 처리할 수 있게 할지를 설정하는 것 (ajax와 같은걸로 요청했을때 응답을 처리할 수 있게 해줄까말까)
        config.addAllowedOrigin("*"); // 모든 IP에 응답 허용
        config.addAllowedHeader("*"); // 모든 헤더에 응답 허용
        config.addAllowedMethod("*"); // 모든 post, get, put, delete 등등 요청을 허용하겠다.
        source.registerCorsConfiguration("/**", config);

        CorsFilter corsFilter = new CorsFilter(source);
        return corsFilter;
    }
}