Origin은 url 주소상에서 프로토콜, Domain 이름, 포트까지 포함한 개념이다.
Origin = [프로토콜]://[Host의 IP 주소 또는 URL]:[포트번호]
대부분의 웹 브라우저는 Same Origin Policy(SOP)라는 보안 정책을 준수한다. 내가 접속한 사이트(Origin)에서 다른 Origin에 요청한 것을 기본적으로 제한해서 어느 정도 해커의 공격에 방어하는 것이다.
CORS는 Cross Origin Resource Sharing의 약자이다. Cross Origin이란 서로 다른 Origin을 뜻하는 말이다. 여기에 붙은 Resource Sharing의 단어까지 포함하면 CORS는 서로 다른 Origin 간의 리소스 교환을 뜻한다.

같은 Origin상에서는 요청이 오는 곳과 처리하는 곳이 동일하기 때문에 특별히 보안상 처리해줄 이유가 없다. 그런데 다른 Origin에서 오는 요청이라면 내가 요청으로 받아온 결과가 믿을만한지 그렇지 않은지 점검하는 과정이 필요하다. 브라우저에서는 결과의 헤더 값을 통해 CORS를 확인한다. 보통 Access-Control-Allow-Origin, Access-Control-Allow-Methods가 브라우저에서 CORS를 검증할 때 사용하는 값이다.

브라우저에서는 localhost:8080 서버에서 전달받은 응답 중 헤더에 Access-Control-Allow-Origin 값을 확인하고 이 값에 현재 Origin이 포함되는지 확인한다. 포함되어 있다면 CORS를 수행하고 그렇지 않으면 에러를 낸다. 위 사진의 빨간 줄은 Origin에 포함되어 있지 않았기 때문에 브라우저가 CORS Error를 발생시킨다.
1) Access-Control-Allow-Origin 허용
CORS 정책에 따라, 출처가 다른 도메인이나 포트에서 리소스를 요청하는 경우에는 브라우저에서 CORS 에러가 발생한다. 이 경우에는 서버 측에서 Access-Control-Allow-Origin 헤더를 설정하여 요청을 허용해야 한다.
2) HTTPS에서 HTTP로 리소스를 요청할 때
보안상의 이유로 HTTPS에서 HTTP로 리소스를 요청하는 경우에도 CORS 에러가 발생할 수 있다. 이 경우에는 HTPPS로 통신하는 서버에서 HTTP로 요청을 전달하는 것이 아니라, HTTPS로 전달해야 한다.
3) Access-Control-Allow-Credentials 허용
CORS 정책에 따라, 인증 정보를 포함한 요청을 보낼 때에는 Access-Control-Allow-Credentials 헤더를 설정해야 한다. 이 헤더가 설정되어 있지 않으면 브라우저는 인증 정보가 포함된 요청을 거부한다.
4) Access-Control-Allow-Methods 허용
CORS 정책에 따라, 허용되지 않은 메서드를 사용하는 요청을 보내는 경우에는 CORS 에러가 발생한다. 이 경우에는 서버에서 Access-Control-Allow-Methods 헤더를 설정하여 요청을 허용해야 한다.
5) Access-Control-Allow-Methods 허용
CORS 정책에 따라, 허용되지 않은 헤더를 사용하는 요청을 보내는 경우에도 CORS 에러가 발생한다. 이 경우에는 서버에서 Access-Control-Allow-Methods 헤더를 설정하여 요청을 허용해야 한다.
자바 spring 서버에서 CORS 관련 헤더 설정하는 코드는 아래를 참고하면 좋을 것 같다.
https://hyeonmin.tistory.com/70
프론트엔드에서는 Proxy 기능을 사용하여 CORS 정책을 우회할 수 있다.
Proxy란 어떠한 대상의 기본적인 동작의 작업을 가로챌 수 있는 객체를 의미한다. 이를 이용한 Proxy Server는 서버와 클라이언트 사이에서 클라이언트가 자신을 통해 다른 네트워크 서비스에 간접적으로 접속할 수 있도록 하는 응용 프로그램을 의미한다.

위의 그림에서는 프론트엔드 서버 말단에 프록시 서버를 도입하여, /api, /api2로 보내지는 요청의 Origin을 API 서버의 Origin과 동일하게 하여 SOP를 위반하지 않도록 할 수 있다.
1) react에서의 프록시 서버 설정
리액트의 경우 http-proxy-middleware 모듈을 이용하여 이를 구현할 수 있다.
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:5000',
changeOrigin: true,
})
);
};
위의 코드를 src 폴더안에 setupProxy.js라는 파일로 작성하면 리액트 서버에 프록시 서버를 도입할 수 있다고 한다.
2) next에서의 프록시 서버 설정
next.js의 경우에는 next.config.js라는 파일을 이용해 상대 주소에 대해서 미리 요청하는 주소를 바꿀 수 있다. 아래 코드는 모든 상대 요청에 대해서 localhost:8080으로 보내는 next.js 코드다. 브라우저에서 보내는 요청이 아니기 때문에 CORS에 걸리지 않게 된다.
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
async rewrites() {
return [
{
source: '/:path*',
destination: 'http://localhost:8080/:path*'
}
]
}
}
module.exports = nextConfig
참고자료
https://selfish-developer.com/entry/%EC%A7%80%EA%B8%8B%EC%A7%80%EA%B8%8B%ED%95%9C-CORS-error-%EC%9D%B4%EC%A0%9C-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EA%B3%B5%EB%B6%80%ED%95%B4%EB%B3%B4%EC%9E%90
https://www.jeong-min.com/30-cors-fe/
https://velog.io/@seungchan__y/CORS-%EC%97%90%EB%9F%AC%EC%99%80-%ED%95%B4%EA%B2%B0%EB%B2%95