URL 구조에서 살펴본 Protocol, Host, Port를 합친 것을 말한다.
브라우저 개발자 도구의 콘솔 창에 location.origin를 실행하면 출처를 확인할 수 있다.
즉, 위 구조에서 Protocl + Host + Port가 같다면 동일 출처라고 한다.
예를 들어, 현재 웹페이지의 주소가
https://themoviedb.org/tv
일 때 같은 출처인지 다른 출처인지 확인해보자.
URL 결과 이유 https://themoviedb.org/main 같은 출처 Protocol, Host, Port 동일 https://themoviedb.org/movie?q=john 같은 출처 Protocol, Host, Port 동일 https://themoviedb.org/movie#john 같은 출처 Protocol, Host, Port 동일 http://themoviedb.org 다른 출처 Protocol 다름 http://themoviedb.org:81/movie 다른 출처 Port 다름 https://themoviedb.api.org 다른 출처 Host 다름
SOP는 다른 출처의 리소스를 사용하는 것을 제한하는 보안 방식을 의미한다.
특정 API를 호출할 때 CORS policy 오류가 발생한 경험이 많을 것이다.
발생하는 이유는 동일 출처 정책(Same-Origin-Policy)를 지켜서 다른 출처의 리소스 접근을 금지하기 때문이다.
하지만, 실제로 웹페이지는 상당히 자주 다른 출처의 리소스를 사용해야 한다.
예를 들어, themoviedb.org 라는 도메인 주소를 사용하는 웹페이지에서 api.themoviedb.org 라는 API 서버로 데이터를 요청해서 화면을 그린다면, 이 웹페이지는 SOP(동일 출처 정책)를 위반한 것이다.
즉, 교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다.
서버에게 바로 요청을 보내는 방법
단순 요청은 서버에 API를 요청하고, 서버는 Access-Control-Allow-Origin
헤더를 포함한 응답을 브라우저에 보낸다. 브라우저는 Access-Control-Allow-Origin
헤더를 확인해서 CORS 동작을 수행할지 판단한다.
서버에 먼저 예비 요청을 보내서 안전한지 판단한 후에 본 요청을 보내는 방법
실제 리소스를 요청하기 전에, OPTIONS
라는 메서드를 통해 실제 요청을 전송할지 판단합니다.
OPTIONS
메서드로 서버에 예비 요청을 먼저 보내고, 서버는 이 예비 요청에 대한 응답으로 Access-Control-Allow-Origin
헤더를 포함한 응답을 브라우저에 보낸다.
브라우저는 단순 요청과 동일하게 Access-Control-Allow-Origin
헤더를 확인해서 CORS 동작을 수행할지 판단한다.
서버에서 Access-Control-Allow-Origin 헤더를 포함한 응답을 브라우저에 보내는 방식으로 CORS 에러를 해결할 수 있다.
서버에 Access-Control-Allow-Origin 등 CORS를 해결하기 위한 몇 가지 응답 헤더를 포함해 달라고 요청해야 한다.
<origin>
| *다음과 같이 응답 헤더가 작성되었다면, https://themoviedb.org 페이지에서 브라우저는 서버 응답으로 온 리소스를 접근할 수 있다.
Access-Control-Allow-Origin: https://themoviedb.org
아래와 같이 *(와일드 카드)가 작성되었다면, 브라우저는 출처에 상관없이 모든 리소스에 접근할 수 있다.
Access-Control-Allow-Origin: *
아래의 다른 방법도 존재한다.
Access-Control-Allow-Methods:
<method>[, <method>]
Access-Control-Expose-Headers:<header-name>[, <header-name>]
Access-Control-Allow-Headers:<header-name>[, <header-name>]
*
Access-Control-Max-Age:<delta-seconds>
Access-Control-Allow-Credentials: true