CORS 에러란?
Cross-Origin Resource Sharing의 약어이다. 한국어로는 교차 출처 리소스 공유이며, 다른 출처(Origin)로 리소스를 요청하는 방식을 일컫는다.
CORS는 최신 브라우저의 동일 출처 정책(Same-Origin Policy) 때문에 등장하게 되었으며, 다른 출처일 때도 리소스를 공유하기 위해 프론트와 백엔드는 별도의 설정을 해주어야 한다.
CORS 에러는 언제 발생할까?
다른 출처(Origin)로 리소스를 요청할 때 발생한다.
URL 구조에서 프로토콜과 호스트가 모든 같은 것을 동일 출처라고 한다. 프로토콜, 도메인, 포트번호 중 하나라도 다르면 다른 출처이다.
이전에는 동일한 도메인에서 리소스를 받아왔는데, 지금은 클라이언트에서 다른 서버(ex. Backend, Oauth)로 리소스를 요청하는 경우가 많이 생겼다.
즉 다른 출처로 리소스를 요청하는 경우이므로 CORS 에러가 발생한다.
CORS 동작방식
웹에서 다른 출처로 리소스를 요청할 때 자동적으로 요청 헤더의 Origin에 출처를 담아서 보낸다.
- 요청 헤더
Origin: https://verilog.io
다른 출처에서 웹에 리소스를 제공할 때 응답 헤더의 Access-Control-Allow-Origin에 허용할 출처를 담아서 응답한다.
- 응답 헤더
Access-Control-Allow-Origin: https://verilog.io
웹에서 응답을 처리할 때 자신이 보낸 Origin과 응답 헤더의 Access-control-Allow-Origin과 비교하여 이 응답이 유효하면 응답을 허용한다.
다를 경우에 이 응답을 버리고 CORS 에러를 발생시킨다.
https://verilog.io
는 같으므로 응답을 허용한다.
모든 출처에 대해 환영
응답 헤더의 Access-Control-Allow-Origin: * 로 모든 출처를 허용하면 모든 응답을 허용하므로, 당장은 편할 수 있지만 보안상 심각한 이슈가 생길 수 있으므로 사용하지 않는 것이 좋다.
따라서 웹에서 다른 서버로 요청할 때 CORS 에러가 생기지 않도록 적절한 해결방법을 선택해야 한다.
백엔드쪽에서 해결하는 방법
가장 정석적인 방법으로 백엔드에서 Access-Control-Allow-Origin을 프론트의 요청헤더인 Origin과 같은 출처로 설정하면 된다.
1. 직접 헤더에 명시
res.setHeader('Access-Control-Allow-origin', '*'); // CORS 허용
res.setHeader('Access-Control-Allow-Credentials', 'true'); // 쿠키 주고받기 허용
res.end();
출처: https://inpa.tistory.com/entry/NODE-📚-CORS-설정하기-cors-모듈 [Inpa Dev 👨💻:티스토리]
2. Express의 cors 미들웨어 사용
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors({
origin: * // CORS 허용
credential: true // 사용자 인증이 필요한 리소스(쿠키 ..등) 접근
}));
출처: https://inpa.tistory.com/entry/NODE-📚-CORS-설정하기-cors-모듈 [Inpa Dev 👨💻:티스토리]
프론트엔드에서 해결하는 방법
정석적인 방법은 아니지만 프론트엔드에서도 해결할 수 있는 방법이 있다.
1. 남이 만든 프록시 서버 사용하기
프록시 서버는 클라이언트가 프록시 서버를 통해 다른 서버에 접속할 수 있도록 해준다.
다시 말해 브라우저와 다른 서버 간의 통신을 중계하는 서버이다.
https://cors-anywhere.herokuapp.com
axios({
method: "GET",
url: `https://cors-anywhere.herokuapp.com/https://api.domain.com`,
headers: {
'APIKey': ${your_API_key},
},
url에 프록시 서버/{url}로 요청하면 CORS를 해결할 수 있다.
2. http-proxy-middleware
리액트에서 배포하기전 로컬 한정일 때 사용하면 좋은 라이브러리이다. (vite는 다른 방법이 있습니다!)
1. npm i http-proxy-middleware
으로 설치한다.
2. src/setupProxy.js 파일 생성 및 작성
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
app.use(
'/api',
createProxyMiddleware({
target: 'http://api.domain.com',
changeOrigin: true,
}),
);
app.listen(3000);
로컬 환경에서 http://localhost:3000/api
로 시작되는요청을 라이브러리가 http://www.api.domain.com/api
로 Origin을 변경하여 CORS 문제를 해결할 수 있다.
이때 createProxyMiddleware의 옵션을 지정할 수 있다.
- target : 리소스를 요청할 서버의 출처
- changeOrigin : target url로 origin의 출처를 변경할 것인지 여부를 나타내며 기본값은 false이다.
출처