브라우저에서 다른 출처에 대한 요청 처리에 대한 정책과 관련된 개념으로 출처인 오리진이 다른 요청은 추가적인 요청 허용을 확인하는 preflight 요청 이후 본 요청을 수행하고 preflight에 대한 응답 헤더에 해당 요청을 허용하지 않는 경우에는 본 요청을 수행하지 않는다.
origin = protocol(https/http) + domain + port
여기서 말하는 동일한 출처란 프로토콜, 도메인, 포트번호가 똑같은 경우일 때를 의미해서 도메인이 같아도 포트번호가 다른 요청에 대해서는 금지하고 있다.
이러한 문제 상황은 리액트 배포 환경의 오리진이 API 서버의 오리진과 다르기 때문에 별도의 서버에 CORS 설정을 하지 않게 되면 리액트 화면에서 API 요청이 발생할 때 다음과 같은 메세지를 크롬 개발자 콘솔창에서 확인할 수 있다.
Access to XMLHttpRequest at
'http://localhost:8080/api/v1/...' from origin
'http://localhost:3000' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on
the requested resource.
GET
, HEAD
, POST
Accept
Accept-Language
Content-Language
Range
Content-Type: application/x-www-form-urlencoded
Content-Type: multipart/form-data
Content-Type: text/plain
Global하게 허용시키고 싶은 경우 WebMvcConfigurer를 구현한 클래스에서 addCorsMappings 메소드를 오버라이딩해서 cors를 허용하도록 한다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
다음과 같이 컨트롤러나 특정 핸들러에 대해서 아노테이션 형태로 cors 설정도 가능하다.
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin
@RequestMapping(method = RequestMethod.GET, path = "/{id}")
public Account retrieve(@PathVariable Long id) {
...
}
}
@CrossOrigin(origins = "http://example.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
...
}
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin("http://example.com")
@RequestMapping(method = RequestMethod.GET, "/{id}")
public Account retrieve(@PathVariable Long id) {
...
}
}