Cross Origin Resource Sharing
CORS는 한 도메인 또는 Origin의 웹 페이지가 다른 도메인 (도메인 간 요청)을 가진 리소스에 액세스 할 수 있게하는 보안 메커니즘이다.
CORS는 서버와 클라이언트가 정해진 헤더를 통해 서로 요청이나 응답에 반응할지 결정하는 방식으로 CORS라는 이름으로 표준화 되었다. CORS는 최신 브라우저에서 구현된 동일 출처 정책(same-origin policy) 때문에 등장했다.
동일 출처 정책은 동일한 출처의 리소스에만 접근하도록 제한하는 것이다. 여기서 출처는 프로토콜, 호스트명, 포트가 같다는 것을 의미한다.
https://naver.com:80을 예시로 들면, https는 프로토콜, naver.com은 호스트명 80은 포트다.
왜 동일한 출처에서만 접근하도록 허용하는 것일까? 모든 출처를 허용하면 어떻게 될까?
https://bank.com 이라는 도메인 사이트가 있다 이 사이트의 api 주소는 https://bank.com/api이다. 사용자가 은행 사이트에서 로그인을 한 후 인증 토큰을 받았다. 그런데 사용자가 로그인한 상태에서 https://evil.com사이트에 접속하게 되면, https://evil.com사이트에서 https://bank.com/api로 ajax 요청을 보낼 때 유저가 획득한 인증 토큰이 자동으로 첨부되어 사용자인척하면서 요청을 보낼 수 있게 된다.
이렇게 자동으로 쿠키가 첨부되기 때문에 보안상의 이유로 브라우저는 HTTP 호출을 동일한 출처로 제한했다.
리액트 개발환경에서, 서버쪽 코드를 수정하지 않고 해결할 수도 있다. 아래와 같이 프록시 속성을 설정하면, 서버에서 해당 요청을 받아준다.
// 프록시 쓰지 않았을때
// localhost:8080(클라이언트 측) --X (CORS)--> domain.com (서버 측)
// 프록시를 설정 후
// localhost:8080(클라이언트 측) --O 프록시가 설정된 Webpack Dev Server--> domain.com (서버 측)
module.exports = {
devServer: {
proxy: {
"/api": {
target: "domain.com",
changeOrigin: true,
},
},
},
};
중간의 프록시 서버 덕분에, domain.com 서버에서는 같은 도메인(domain.com)에서 온 요청으로 인식하여 CORS 에러가 발생하지 않는다.
create-react-app 으로 생성한 프로젝트에서는, package.json 에 proxy 값을 설정하여 proxy 기능을 활성화 하는 방법도 있다.
{
//...
"proxy": "http://localhost:4000"
}
프록시 서버는 클라이언트가 자신을 통해서 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해준다.
컴퓨터 네트워크에서 다른 서버상의 자원을 찾는 클라이언트의 요청을 받아 중계하는 서버를 말한다.
쉽게 말해 중계서버라고 생각하면 된다.
서버와 클라이언트 사이의 중계자 역할로 대리통신을 수행하는 것을 가리켜 '프록시',
그 중계기능을 하는 서버를 '프록시 서버'라고 부른다.
주로 보안상의 문제로 직접 통신을 송수신할수 없는 상황에서 프록시를 이용하여 중계통신을 하는데 사용한다.
프록시 서버는 서버위치에 따라 크기 두가지로 나뉜다.
예를 들어 그림과 같이 클아이언트가 example.com에 연결하려고 하면 클라이언트 PC에서 직접 연결하는게 아니라,
포워드 프록시 서버가 앞단에서 먼저 요청을 받은 후, 인터넷에 연결하여 그 결과를 클라이언트에게 전달(forward)해준다.
클라이언트가 example.com 웹 서비스에 데이터를 요청하면 Reverse Proxy는 이 요청을 받아서 내부 서버에서 먼저데이터를 받은 후에, 이 데이터를 클라이언트에게 전달하게 된다.