브라우저와 서버간에 보안을 위해 도입된 정책이다. 브라우저는 보안상의 이유로 다른 오리진의 리소스에 접근하는 것을 제한한다. 이를 해결하기 위해 CORS 정책이 도입되었다.
목차
CORS란?
CORS(Cross-Origin Resource Sharing)는 교차 출처 리소스 공유를 의미한다. 예전에는 프론트엔드와 백엔드를 따로 구성하지 않고 한 번에 구성해서 모든 처리가 같은 오리진 안에서 가능했습니다. 그래서 다른 오리진에 리소스를 요청하는 것은 당연히 의심스러운 행동일 수 밖에 없었습니다. 하지만 최근에는 프론트엔드와 백엔드를 분리하는 것이 일반적이 되었고, 이로 인해 다른 오리진에 리소스를 요청하는 경우가 많아졌습니다. 이때 CORS 정책이 도입되었습니다. 출처가 다르더라도, 서버에서 허용하는 경우에만 리소스를 요청할 수 있도록 말입니다.
CORS 동작 방식
서버에서는 클라이언트의 요청을 받았을 때, 응답 헤더에 Access-Control-Allow-Origin
헤더를 포함하여 클라이언트에게 허용된 오리진을 알려줍니다. 클라이언트는 서버로부터 받은 헤더를 확인하여 요청이 허용되었는지 판단합니다. 만약 허용되지 않은 요청이라면 브라우저는 CORS 정책에 위배되었다는 에러를 발생시킵니다.
브라우저에서는 SOP(Same-Origin Policy) 정책을 따르는 요청(fetch, XMLHttpRequest)을 보낼 때, 특히 사이드 이펙트를 가지는 요청에 대해서는 브라우저가 자동으로 preflight 요청을 보내게 됩니다. preflight 요청은 실제 요청을 보내기 전에 서버에게 요청을 보내 허용되는지 확인하는 요청입니다. preflight 요청은 OPTIONS
메서드로 보내며, 서버로부터 “승인”을 받은 후 실제 요청을 보냅니다.
또한 기본적으로 SOP 정책을 따르는 요청은 교차출처 요청을 보낼때, 쿠키를 전송하지 않습니다. 쿠키를 전송하려면 fetch에서는 credentials
옵션을 include
로 설정해야 하고, XMLHttpRequest에서는 withCredentials
프로퍼티를 true
로 설정해야 합니다. 이때 브라우저는 응답에서 Access-Control-Allow-Credentials: true
가 없으면 해당 응답을 무시합니다.
localhost에서 CORS 에러 해결하기
여기서 중요한 점은 CORS 정책은 브라우저와 서버간의 통신에서 브라우저가 보안상의 이유로 요청을 제한하기 위해 사용하는 정책이기에 서버간에 통신에는 영향을 주지 않는다. 그렇기 때문에 프론트 개발서버에서 proxy를 사용하면 해결할 수 있다. vite를 기준으로 설명하면 쉬운데
// vite.config.js
export default {
...
server: {
proxy: {
'/api': {
target: '백엔드서버',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
}
이런식으로 설정하면, 브라우저의 오리진은 localhost:port
로 프록시서버와 동일하게 되고, 프록시서버에서는 따로 요청이나 응답을 차단하지 않기때문에, 프록시서버는 백엔드 서버에서 응답을 받아올 수 있다.
결론
CORS는 브라우저와 서버간의 통신에서 브라우저가 보안상의 이유로 요청이나 응답을 제한하기 위해 사용하는 정책이다. 서버간에 통신에는 영향을 주지 않는다. 프론트 개발서버에서 proxy를 사용하면 CORS 에러를 해결할 수 있다.