CORS 동작방식과 해결방법

SeokHwan An·2022년 10월 27일
0

저번 포스팅에서는 CORS의 개념과 왜 사용하는지를 정리해보았습니다. https://velog.io/@seokhwan-an/CORS를 참고하시면 보실 수 있습니다.

이번 포스팅에서 CORS가 어떻게 동작하는지를 확인하고 이를 해결해보는 방법에 대해 알아보겠습니다.

앞선 포스팅에서 간단하게 정리했는데 CORS의 큰 원리는 클라이언트가 서버로 요청을 보낼 때 http message header 부분에 Origin에 자신의 출처를 보내고 서버는 응답으로 Access-Control-Allow-Origin에 허용된 출처를 보내주어 브라우저에서 이를 확인해 보내준 리소스의 유효성을 판단합니다. 간단해 보이지만 크게 2가지의 시나리오가 존재합니다.

CORS의 동작방식

1. Preflight Request
프리플라이트(Prefligt) 방식은 자주 접할 수 있는 시나리오 입니다. 간단하게 요약을 하면 클라이언트가 본 요청을 보내기 전에 예비 요청을 보내므로써 요청에 대한 응답이 유효한지를 파악하는 것입니다. 이 때에는 http 메소드 중에 OPTION 메소드가 활용됩니다.

💡OPTION 메소드
The HTTP OPTIONS method requests permitted communication options for a given URL or server. A client can specify a URL with this method, or an asterisk (*) to refer to the entire server.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS

OPTION 메소드는 주어진 URL 또는 서버에 대해 허용된 통신 옵션을 요청하는 메소드입니다.

위의 그림을 보면 알 수 있듯이 javascript에서 fetch API를 통해 브라우저에게 서버로부터 응답 리소스를 받아오라는 요청을 보내면 브라우저는 먼저 서버에게 예비요청을 보내고 예비요청에 대한 응답이 유효하다가 판단이 되면 본 요청을 보내서 서버로 부터 리소스를 받아오는 방식입니다.

OPTION 요청을 보내는 것은 특정 조건이 만족하지 않는 경우에 보내게 되는 것입니다.

  • GET, HEAD, POST 메소드 중 하나
  • user agent에 의해 자동으로 설정되는 (Connection, User-Agent, Fetch 스펙상 forbidden header로 정의되어 있는) 헤더외에 CORS-safelisted request-header로 명시된 헤더들만 포함된 경우 (Accept, Accept-Language, Content-Language, Content-Type 등)
  • Content-Type은 application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나
    이 중에 만족하지 않은 경우에 OPTION 메소드를 활용한 예비 요청을 보내게 되는 것입니다.

2. Simple Request
단순 요청(simple request)은 예비요청을 보내지 않고 바로 서버로 요청을 보내어 서버로 부터 응답을 받고 브라우저에서 유효성을 파악하는 방법입니다. Preflight request와 큰 맥락은 같고 예비요청을 보내는 여부와의 차이가 있습니다.


simple request가 이루어지기 위해서는 앞선 언급한 조건들이 모두 만족하는 경우 입니다.

이제는 실제 개발에서 CORS를 해결하는 방법에 대해 설명하겠습니다. 저는 스프링을 이용하여 개발 학습을 진행하는 만큼 스프링에서 이용하는 CORS 해결방식을 제시하겠습니다.

CORS 해결방법

  1. @CrossOrigin 사용
    가장 간단한 방법인데 CrossOrigin 어노테이션을 컨트롤러 단에 사용하는 방식과 메소드 단에 사용하는 방식이 있습니다. originPatterns 속성을 활용해 허용할 출처를 설정하면 됩니다.
@CrossOrigin(originPatterns = "허용할 출처")
@RestController
public class TestController {
	
    @GetMapping()
    public String test() {
    	return "test";
    }	
@RestController
public class TestController {
	
    @GetMapping()
    @CrossOrigin(originPatterns = "허용할 출처")
    public String test() {
    	return "test";
    }	

단점으로는 controller가 많아지거나 method가 많아지면 사용해야할 어노테이션 수가 많아집니다.

  1. WebMvcConfigurer 활용하기
    WebMvcConfigurer를 상속한 클래스를 만드로 addCorsMapping()을 재정의하면됩니다.
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("허용할 출처")
                .allowedMethods(HttpMethod.GET.name());
    }
}

allowedOrigins에서는 허용한 출처를 정하는 것이고 allowedMethods에서는 허용할 http 매소드를 설정합니다.

이외에도 프록시 서버를 이용해서 CORS를 우회하는 방식이 있는데 이부분은 잘 이해가 되지 않아서 학습을 더한 이후에 추가해 놓겠습니다.

reference

https://evan-moon.github.io/2020/05/21/about-cors/
https://steady-coding.tistory.com/616

0개의 댓글