CORS 헤더 설정을 따로 하지 않은 서버에 다른 출처에서 요청을 보내는 경우 다음과 같이 CORS 에러가 표시된다.
이는 동일 출처 정책(SOP)에 의해 차단되는 다른 출처에서의 요청을 허용하기 위해서는 CORS 정책의 Access-Control-Allow-Origin
헤더에 요청을 보내려는 출처가 명시돼 있어야 하는데 명시돼 있지 않아 나타나는 에러 메시지다.
따라서 위 에러를 해결하려면 CORS 헤더를 설정해 주어야 한다.
여기서 사용하는 서버는 express
서버라서 cors 라이브러리를 설치해 헤더를 적용할 것이다.
npm install cors
const cors = require('cors');
app.use(
cors({
'Access-Control-Allow-Origin': '*', // 모든 출처로부터 요청 허용
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Accept',
'Access-Control-Max-Age': 10,
})
);
이렇게 헤더를 적용해 주면, 더 이상 cors 에러 메시지가 발생하지 않는다.
cors 헤더를 설정하는 것은 서버 쪽에서 해야 하는데, 클라이언트에서 프록시 기능을 사용해 이를 해결할 수도 있다.
proxy란 클라이언트에서 서버로 접속할 때 클라이언트가 직접 접속하지 않고 대리로 접속할 수 있게 중계자로써 기능하는 것을 말한다.
서버로 요청을 보내고 응답을 받는 기본적인 흐름은 다음과 같다.
즉, 요청을 보내는 출처가 서버에서 허용한 출처인지 검사하고 통과되어야만 서버로부터 리소스를 획득할 수 있다.
여기서 proxy를 적용하면 흐름은 다음과 같이 바뀐다.
/ 수정 필요 /
CRA로 만든 React 앱의 package.json을 열어 요청하려는 주소를 proxy로 적어준다.
(...)
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"proxy": "http://localhost:3080"
}
그리고 코드에서 요청을 보내려는 URL에서 proxy로 작성한 부분을 지워준다. (요청하는 도메인이 생략된 경우 현재 페이지의 도메인(ex. http://localhost:3000)을 가리키게 됨)
export const getAllBooks = async () => {
// const response = await fetch('http://localhost:3080/api/books');
const response = await fetch('/api/books');
return await response.json();
};
코드를 작성하고 요청을 보낸 다음 네트워크 탭에서 보낸 요청을 확인해 보면, http://localhost:3080/api/books
가 아닌 http://localhost:3000/api/books
에 요청을 보냈음을 알 수 있다. (포트번호 차이)
결론적으로 http://localhost:3000
이라는 출처에서 동일한 출처로 요청을 보냈기 때문에 CORS 에러가 발생하지 않는다.
서버가 여러 개인 경우, proxy를 객체로 작성하면 된다.
(...)
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"proxy": {
"/api1/": {
"target": "http://localhost:1000"
},
"/api2/": {
"target": "http://localhost:2000"
},
"/auth/": {
"target": "http://localhost:4000"
},
}
}
라이브러리를 설치한다.
npm install http-proxy-middleware
프록시를 셋팅하기 위해 setupProxy.js 파일을 src 폴더에 생성하고 다음과 같이 작성한다.
app.use를 호출해 여러 개의 도메인을 작성할 수 있다.
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:3080',
changeOrigin: true,
})
);
app.use(
'/api2',
createProxyMiddleware({
target: 'http://localhost:3070',
changeOrigin: true,
})
);
};
target
: 엔드포인트를 제외한 출처(프로토콜, 호스트, 포트번호)changeOrigin
: 호스트 헤더의 출처를 target으로 변경할지 여부 (cors 통과 위해 true로 바꿔줌)