Mdn web docs - CORS를 통해 학습한 내용을 정리한 글입니다. 이전 글과 이어집니다.
CORS
CORS(Cross-Origin Resource Sharing, 교차 출처 리소스 공유)란 HTTP 헤더를 이용하여 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처(도메인, 프로토콜, 포트)의 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다.
기본적으로 브라우저는 스크립트에서 시작한 교차 요청을 제한한다. 이러한 규약을 동일 출처 정책이라 하며, XMLHttpRequest나 Fetch API가 이를 따른다. 이 외에도 CSS 내에서 @font-face를 통해 사용하는 웹 폰트나, WebGL 등이 있다. 다른 출처의 리소스를 정상적으로 받아오기 위해서는, 그 출처에서 올바른 CORS 헤더를 포함한 응답을 반환해야 한다. 이를 통해 받아오는 데이터의 안전성을 어느 정도 보장 받는 것이다.
동작 방식
사전확인 (Preflight Requests)
브라우저가 웹 페이지로부터 교차 출처 요청이 안전하게 수행될 수 있는지 확인하는 매커니즘이다. 실제 요청(GET /resources)을 보내기 전에, HTTP Options 메서드를 사용하여 제공된 헤더를 검사하고 실제 요청을 허용할지 결정한다.
단순 요청 (Simple Requests)
Prefilght를 트리거하지 않는 요청들을 말한다. 사용가능한 메서드와 헤더, Content-type 등을 전부 만족시켜주어야 단순 요청이 발생한다. 하나라도 만족하지 않는 경우, 브라우저는 자동으로 Preflight 요청을 발생시킨다.
아래는 https://foo.example에서 https://bar.other의 자원을 사용할 때의 예시이다.
const xhr = new XMLHttpRequest();
const url = 'https://bar.other/resources/public-data/';
xhr.open('GET', url);
xhr.onreadystatechange = someHandler;
xhr.send();
먼저 통신을 시작하고, CORS 헤더를 사용해 권한을 처리한다.
GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example
요청 헤더 내용으로, Origin 속성에 요청을 보내는 출처를 포함시켜 보내면 된다.
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml
[…XML Data…]
서버는 위와 같이 응답 데이터를 반환하며, Access-Control-Allow-Origin 속성에서 요청한 리소스에 대한 접근 권한을 설정할 수 있다. 특정 도메인을 기입하거나, '*'를 통해 모든 접근을 허용할 수 있다.
자격 증명 요청 (Credentialed Requests)
쿠키 혹은 HTTP 인증 등의 사용자 인증 정보를 함께 보내는 요청을 말한다. 헤더의 Credentials : "include' 옵션을 설정하여 제어가 가능하며, Preflight 요청과 병행될 수 없다.