React를 개발할 때, 보통 react-script start를 통해 React dev server를 띄어놓고 개발을 한다.
React dev server의 접속 주소는 보통 http://localhost:3000 을 사용한다.
만약 api server의 주소가 http://apiserver.com:5000이라고 하면, 따로 CORS설정을 해놓지 않은 이상,
api request를 날리면 CORS 오류가 뜬다.
Access to fetch at ’https://apiserver.com:5000/api/test’ from origin ’http://localhost:3000’ has been blocked by CORS policy: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ’*’ when the request’s credentials mode is ‘include’.
react-script 공식 홈페이지 문서에 proxy를 설정하는 방법이 있다.
package.json에 proxy 한 줄을 추가하면 된다!
//package.json
{
...,
"proxy": "http://apiserver.com:5000",
...,
}
그러면 다음과 같이 request가 처리된다.
문제해결!! 일줄 알았으나..
서버와의 양방향 통신을 위해, 보통 websocket을 많이 사용한다.
websocket으로 서버와 통신할때는 protocol을 http가 아니라 ws를 사용하게 된다.
ex)
ws://apiserver.com:5000/socketio?...
위의 방법처럼 proxy를 설정하게되면, websocket 요청들의 protocol이 http로 바뀌어서 서버에 전달되서 websocket을 사용할 수 없게 된다.
github issue: Setting "proxy" in package.json Fails for WebSockets
위 이슈에서 제시한 해결책은 http-proxy-middleware라는 모듈을 사용하는 것이다.
option에 ws: true를 주면되는군..!
react-script의 공식문서에도 proxy를 manual하게 설정하는 방법이 나와있다.
두 가지를 조합해봤을때, src/SetupProxy.js를 만들어서 아래와 같이 만들면 될 것 같았다.
// src/SetupProxy.js
// failed code
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://apiserver.com:5000',
changeOrigin: true,
ws: true
})
);
app.use(
'/socket.io',
createProxyMiddleware({
target: 'ws://apiserver.com:5000',
changeOrigin: true,
ws: true
})
);
};
websocket 요청은 /socket.io로 그냥 api 요청은 /api로 나누어져서 잘 들어가질 것이라 생각했다.
하지만, 결과는 실패... 😥
뭔가 원하는대로 request들이 분류가 잘 안되는 것 같았다.
열심히 구글링한 결과 두 가지를 알아냈다.
1. filtering을 잘못하고 있었다.
뭔가 filtering이 이상해서 http-proxy-middleware 코드를 살펴봤다.
createProxyMiddleware에 인자를 하나만 넣으면 option이고, 두개를 넣으면 filter, option인 것 같다!
filter를 app.use의 첫 argument에 넣지말고, createProxyMiddleware의 첫 인자에 넣어보자!
2. http-proxy-middleware의 README를 읽어보며 router라는 좋은 옵션을 발견했다.
굳이 app.use를 2개 만들지말고 이 옵션을 사용해보자!
2가지를 고려해서 새로운 SetupProxy.js를 만들었다.
// src/SetupProxy.js
const createProxyMiddleware = require('http-proxy-middleware')
module.exports = app => {
app.use(
createProxyMiddleware(
['/api', '/socket.io'],
{
target: 'http://nginx:80',
changeOrigin: true,
ws: true,
router: {
'/socket.io': 'ws://nginx:80'
}
}
)
)
}
문제해결!!
스프링에 리액트 연동하려고 프록시 관련으로 알아보고 있었는데 잘 참고하겠습니다.