기본적으로 브라우저는 SOP(Same Origin Policy) 정책을 따릅니다.
이는 보안을 위해 같은 출처 내의 자원에만 접근이 가능하게 합니다.
하지만 다른 출처의 자원에 접근이 필요한 경우에 CORS를 통해 요청과 응답을 주고받을 수 있게 해야 합니다.
CORS(Cross Origin Resource Sharing)란 다른 출처의 자원에 접근하기 위한 방법입니다.
CORS의 앞 두 글자는 Cross Origin을 의미합니다.
다른 origin의 경우에 대해 자원을 공유할 수 없다는 의미입니다.
따라서 이 origin이라는 것이 무엇을 의미하는지 알아야 합니다.
Origin = Protocol + Domain + Port
Origin은 Protocol, Domain 그리고 Port를 합친 것을 의미합니다.
example>
URL | https://velog.io:443/@baehyeonsik?id=hyeonsik |
---|---|
Protocol | https:// |
Domain | velog.io |
Port | :443 |
Path | /@baehyeonsik |
Query String | ?id=hyeonsik |
여기서 Origin은 https://velog.io:443
이 됩니다.
CORS 동작은 기본적으로 클라이언트와 서버 간 Origin
정보를 확인하는 것입니다.
동작방식을 보다 자세히 나누면 아래와 같이 세 가지로 나뉩니다.
Simple Request로 취급되는 조건은 아래의 경우에 한합니다.
GET
, POST
, HEAD
Accept
, Accpet-Language
, Content-Languae
, Content-Type
application/x-www-form-urlencoded
, multipart/form-data
, text/plain
위 조건을 만족해 Simple Request로 취급된다면 아래와 같이 Cross-Origin 간 자원에 접근 가능합니다.
브라우저에서 요청 시, Origin
헤더에 Origin 정보를 담아서 요청
서버에서 응답 시, Allow-Control-Allow-Origin
헤더에 허가된 Origin 정보를 담아서 응답
브라우저에서 받은 응답의 Allow-Control-Allow-Origin
헤더의 정보에 요청 시 보낸 Origin
헤더의 정보가 담겨있는지 검사
위 순서를 거쳐 응답이 안전하다고 판단되면 응답을 가져오고, 그렇지 않다면 응답을 파기하게 됩니다.
Preflight Request 방식은 OPTIONS 메소드를 통해 CORS 정보 확인 후, 재요청을 보내는 방식입니다.
브라우저에서 요청 시, OPTIONS 메소드로 아래 헤더에 정보들을 포함해 요청합니다.
Origin
: Origin 정보
Access-Control-Request-Method
: 요청 메소드 종류
Access-Control-Request-Headers
: 요청 헤더 종류
서버에서 응답 시, 아래 정보들을 포함해 응답합니다.
Access-Control-Allow-Origin
: 허가된 Origin 정보
Access-Control-Allow-Methods
: 허가된 메소드 정보
Access-Control-Allow-Headers
: 허가된 헤더 정보
Access-Control-Max-Age
: Preflight 유효 시간
실제 요청이 안전하다고 판단될 경우, Simple Request와 유사하게 보내려던 요청을 시도합니다.
요청에 사용자 식별 정보가 담긴 경우, 추가 처리가 필요합니다.
쿠키나 토큰 등의 정보를 서버에서 전송하기 위해 옵션 값을 아래와 같이 설정합니다.
XMLHttpRequest, ajax, axios 의 경우
withCredentials : true
fetch 의 경우
credentials : include
이 경우에 서버의 응답 중 Allow-Control-Allow-Origin
헤더의 값으로 *
가 아닌 Origin 값이 포함되어야 합니다.
또한 Allow-Control-Allow-Credentials
헤더의 값이 true로 설정되어야 합니다.
개발 환경을 구축하는 경우 CORS 에러를 해결하기 위해 Reverse Proxy를 사용하는 방법도 있습니다.
현재 개발중인 서비스에서는 nginx를 프록시 서버로 설정하여 origin을 통일시켰습니다.
이 외에 webpack의 proxy값을 설정하여 해결하는 방법도 있습니다.!