July 26, 2020
Issue Tracker React 프로젝트에서 axios
를 사용하여 백엔드 서버에 POST 요청시 아래와 같은 에러가 발생했다.
Access to XMLHttpRequest at 'http://.../api/labels' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
webpack.dev.js
const merge = require("webpack-merge");
const common = require("./webpack.common.js");
module.exports = merge(common, {
mode: "development",
devtool: "inline-source-map",
devServer: {
historyApiFallback: true,
inline: true,
port: 3000,
hot: true,
publicPath: "/",
open: true,
},
});
Chrome DevTools Network 탭에서 확인해보니 OPTIONS, POST 총 2번의 요청을 보냈고,
각각의 Header를 살펴보니 다음과 같았다.
OPTIONS 요청
POST 요청
문제는 외부에 있는 백엔드 서버에 POST 요청을 보내기 위해 preflight 요청을 먼저 보내서 POST 요청 권한 유무를 확인했는데,
이때 권한이 없다는 응답(403
)을 받아서 POST 요청을 보내지 못했기 때문이었다.
CORS 관련 webpack의 ‘proxy’ 설정에 대해 알게되었다.
proxy 설정은 외부 도메인에 대한 요청과 응답을 webpack 또는 webpack-dev-server가 처리할 수 있게 해주는 옵션이다. 쉽게 얘기하면 외부 도메인으로 보내는 요청을 가로채서 외부 백엔드 서버로 전달하고, 다시 백엔드 서버로부터 온 응답을 가로채서 브라우저쪽으로 반환해주는 것이다.
요청과 응답을 가로채서 필요에 따라 ‘적절한 처리’를 해줄 수 있기 때문에 백엔드의 코드를 수정하지 않고도 CORS 이슈를 해결하는 방법이 될 수 있다.
CRA를 사용하는 경우 package.json
에 proxy 설정을 추가해주면 되고, dev-server를 사용하는 경우 webpack config 파일에서 devServer 설정값으로 proxy를 추가해주면 된다.
CRA
webpack-dev-server
이번 CORS 이슈는 백엔드에서 Spring에 다음과 같은 설정을 추가한뒤 해결됐다.
WebConfig.java
(...)
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE")
.allowedOrigins("http://localhost:3000");
}
webpack / webpack-dev-server의 proxy라는 설정과 관련 자료들을 찾아보면서 http, 네트워크 공부의 필요성을 절감했고 추가로 공부해볼 내용들을 정리할 수 있었다.