Table of contents
스프링부트가 제공하는 SOP와 CORS에 대해 알아보자.
SOP
Single-Origin Policy(SOP) 에서는 같은 origin 에만 요청을 보낼 수 있다.
스프링부트는 기본적으로 SOP가 적용되어 있다. 즉, 기본적으로는 origin이 다른 경우 리소스를 요청할 수 없다.
origin
- URI 스키마 (http, https)
- hostname (whiteship.me, localhost)
- 포트 (8080, 18080)
위의 세가지를 조합한 결과가 하나의 origin이다. 예를 들어 http://localhost:8080에서 REST API를 제공하는 서버가 있고, http://localhost:18080 에서 사용하는 어떠한 애플리케이션에서 해당 REST API 서버에 HTTP 요청을 보내도 SOP를 위반하여 리소스를 응답받을 수 없다.
CORS
Cross-Origin Resource Sharing(CORS)는 서로 다른 origin 끼리 리소스를 공유할 수 있다.
스프링 MVC에서 CrossOrigin를 지원한다. 스프링에서 CORS를 지원하기 위해서 원래는 여러가지 설정을 해야하지만, 스프링부트에서 그러한 설정을 해주기 때문에 @CrossOrigin을 바로 사용할 수 있다.
실습
CORS 실습을 위해 서버와 클라이언트 애플리케이션을 준비하자.
@SpringBootApplication
@RestController
public class WebmvcCorsApplication {
@GetMapping("hello")
public String hello() {
return "hello";
}
public static void main(String[] args) {
SpringApplication.run(WebmvcCorsApplication.class, args);
}
}
서버 애플리케이션에는 간단하게 GET /hello에서 hello 문자열을 반환하는 REST 컨트롤러 하나만 작성하여 8080 포트에서 실행한다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script>
$(function() {
$.ajax("http://localhost:8080/hello")
.done(function(msg) {
alert(msg);
})
.fail(function() {
alert("fail");
});
});
</script>
</body>
</html>
클라이언트 애플리케이션에는 index.html 을 정적리소스 경로에 생성하여 welcome 페이지 지정하며, 18080 포트에서 실행한다. origin이 다른 localhost:8080에 Ajax GET 요청을 전송하여 결과를 출력한다. 지금 상태에서는 fail 콜백이 수행될 것이다.
(index):1 Access to XMLHttpRequest at 'http://localhost:8080/hello' from origin 'http://localhost:18080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
클라이언트는 요청을 전송하기 전에 서버로부터 Access-Control-Allow-Origin를 요청한다. Access-Control-Allow-Origin 헤더에 있는 정보와 클라이언트 자신이 매치가 되면 실제 요청을 보낼 수 있다.
앞서 설명한 것처럼, 스프링부트는 기본적으로 SOP가 적용되어 있기떄문에 다른 origin에게 리소스를 요청할 수 없다. 서버에 CORS 설정을 추가해보자.
@SpringBootApplication
@RestController
public class WebmvcCorsApplication {
@CrossOrigin(origins = "http://localhost:18080")
@GetMapping("hello")
public String hello() {
return "hello";
}
public static void main(String[] args) {
SpringApplication.run(WebmvcCorsApplication.class, args);
}
}
@CrossOrigin을 지정하면서 origins 속성에 CORS를 허용할 origin을 문자열로 지정한다. 여기서는 클라이언트의 origin인 http://localhost:18080을 지정했다.
서버를 다시 시작한 뒤, 클라이언트에서 Ajax 요청을 다시 보내면 이번에는 done 콜백이 실행된다.
@CrossOrigin는 클래스나 @RequestMapping에 지정할 수 있다.
전역 설정
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:18080");
}
}
WebMvcConfigurer 전역으로 CORS를 설정하여 한 곳에서 관리할 수 있다.
해당 포스팅은 스프링 부트 개념과 활용 강의 내용을 토대로 작성하였습니다.