본문 바로가기

Java and Spring

CORS(Cross-Origin Resource-Sharing)란?

개발한지 4년이 되었지만, 그 동안 회사에서 SSR(Sever-side Rendering)기반으로 프론트와 백엔드를 개발하다보니 출처가 다른 환경에서 API를 호출해본적이 없어서 CORS의 개념에 대해서 전혀 모르고 있었습니다.

그러던 중 우아한 테크에서 진행하는 [10분 테크톡]에서 CORS라는 주제로 발표하는 것을 보고 추후에 프론트와 백엔드가 나뉘어진 회사에서 CORS문제를 겪을수도 있을 것 같다는 생각이 들게 되어 공부하게 되었습니다.

 

  • SOP란?
  • CORS란?
  • CORS 해결법
SOP(Same-Origin Poicy)란?

먼저, CORS문제를 겪게되는 이유는 SOP정책 때문입니다.

SOP란, 동일 출처 정책이라해서 하나의 출처에서 자원을 얻기 위해서는 동일한 출처에서 접근을 해야 한다는 정책입니다.

여기서 출처란, 보통 주소를 의미하는데 http://localhost:8080이라는 출처가 있으면 http = 프로토콜(Protocal), localhost = 호스트(Host), 8080 = 포트(Port) 이 3가지 중 하나라도 다르면 브라우저에서 SOP정책을 위반했다고 판단하여 서로 다른 출처에서 자원을 가져오지 못하게 하는 방식입니다.

 

그렇다면, SOP는 왜 필요한 것일까요?

만약, 우리가 중요한 정보를 저장하고 있는 사이트에 로그인을 하였다고 가정해봅시다. 로그인을 하였으면 세션이 유지되기 때문에 일정 시간동안은 로그인을 하지않아도 해당 사이트에서 다양한 API호출이 가능합니다. 만약 어떤 해커가 우리에게 Mail을 보내고 우리가 아무 생각없이 URL을 클릭하여 "www.badsite.com"이라는 나쁜 사이트에 접속을하게 되었고, 그 순간 그 사이트에 심어둔 자바스크립트가 작동하여 중요한 정보를 저장하고 있는 사이트에 Delete요청을 보내게 된다면, 우리는 속수무책으로 중요한 정보를 모두 날려버리게 됩니다. 그래서 SOP정책이 필요한 이유입니다.

 

CORS(Cross-Origin Resource-Sharing)란?

SOP와 같은 동일 출처 정책이 필요한건 맞지만, 요즘에는 외부에서 제공해주는 오픈 API를 사용하여 개발하는 경우가 많기 때문에 출처가 다르더라도 자원을 공유할 수 있도록 하는 방식이 바로 CORS입니다.

 

CORS의 요청정책은 총 3가지가 있습니다.

1. 단순 요청(Simple Request)

2. 프리플라이트 요청(Preflight Request)

3. 신용 요청(Credentialed Request)

이번 포스팅에서는 1번 단순요청으로 CORS문제가 발생되는 현상을 재현해보도록 하겠습니다.

 

아래 이미지는 로컬에서 AWS EC2에 있는 API를 호출한 이미지입니다.

왼쪽은 로컬 HTML파일이고 화면 진입 후, 자바스크립트에 의해 API호출 시 오른쪽 이미지와 같이 개발자도구에 CORS문제가 발생했다는 에러 문구입니다.

요청 출처 : http:localhost:8080

응답 출처 : http://54.180.150.6:8080/hello

위에서 정의한 3가지 프로토콜, 호스트, 포트 중 호스트가 다르기 때문에 CORS문제가 발생하였습니다.

 

CORS 해결법

이러한 CORS문제를 해결하려면 서버쪽에서 설정을 해줘야 하는데 총 2가지 방법이 있습니다.

1. @CrossOrigin사용

아래와 같이 @CrossOrigin을 사용하게되면 http://localhost:8080에서 들어오는 요청중 TestController에 있는 메소드에 대해서만 CORS문제가 해결됩니다.

@CrossOrigin(origins = "http://localhost:8080")
@Controller
public class TestController {
    @GetMapping("/hello")
    public String hello(){
        return "dmswo";
    }
}

2. WebMvcConfigurer에서 전역으로 설정하기

전역으로 설정하게 된다면, WebMvcConfigurer에 있는 addCorsMappings메소드를 구현하면 되는데, 여러 설정 정보로 허용할 출처와 Http Method도 정할 수 있기 때문에 커스텀하게 CORS를 허용하고 싶다면 @CrossOrigin보다는 전역설정 방법이 더 좋다고 생각합니다.

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        WebMvcConfigurer.super.addCorsMappings(registry);
        registry.addMapping("/**")  // URL 패턴
                .allowedOrigins("http://localhost:8080")  // 허용하는 출처
                .allowedMethods(HttpMethod.GET.name());  // 허용하는 Http Method
    }
}

해당 코드를 적용하고 로컬에서 해당 Html화면을 다시 접속하면, 자바스크립트가 실행되어 제가 올려놓은 EC2서버에 "http://54.180.150.6:8080/hello"라는 API를 호출하게 됩니다.

 

WebMvcConfigurer에 코드를 적용하기 전에는 아래와 같이 CORS문제가 발생하였지만

 

WebMvcConfigurer에 코드를 적용한 후에는 CORS문제가 발생하지 않는 것을 확인할 수 있습니다.