Restful API를 활용한 통신을 하며 나를 괴롭혔던 CORS에러를 포스팅 해보려고 한다.
CORS는 Cross-Origin Resource Sharing 의 줄임말로 교차 출처 리소스 공유라고 해석한다.
서버의 위치를 의미하는 https://google.com과 같은 URL들은 하나의 문자열 같아 보여도, 여러 개의 구성 요소로 이루어져있다.
이때 출처는 Protocol과 Host, 그리고 위에 나와있지 않은 :4000, : 80 과 같은 포트번호까지 모두 합친것을 의미한다.
또한 출처 내의 포트번호는 생략이 가능한데, 이는 웹에서 사용하는 HTTP / HTTPS 프로토콜의 기본 포트 번호가 정해져 있기 때문이다.(기본 포트는 :80)
SOP는 지난 2011년에 처음 등장한 보안 정책으로 말 그대로 같은 출처에서만 리소스를 공유 할 수 있다.
라는 규칙을 가진 정책이다.
이렇게 다른 출처의 리소스를 사용하는 것을 제한하는 행위는 귀찮음을 만들어내는 것 같지만, 굉장히 중요한 것들이다.
클라이언트 어플리케이션은 사용자의 공격에 너무 취약한 환경을 가지고 있다. 당장 개발자 도구만 열어도 DOM이 어떻게 작성되어 있고, 어떻게 통신하는지 다 열람이 가능하기 때문이다.
통신에 대해 아무런 제약도 존재하지 않는다면, CSRF(Cross-Site Request Forgery)나 XSS(Cross-Site Scripting)와 같은 방법을 사용하여 어플리케이션의 코드가 실행된 것 처럼 꾸며 사용자의 정보를 탈취하기가 너무나도 쉬워진다.
본격적으로 어떤 방법을 통해 서로 다른 출처(Cross-Origin)에서 리소스를 안전하게 사용할수 있는지 알아보자.
기본적으로 웹 클라이언트 어플리케이션이 다른 출처의 리소스를 요청할 때는 HTTP 프로토콜을 사용하여 요청을 보내게 되는데, 이때 브라우저는 요청 헤더에 Origin이라는 필드에 요청을 보내는 출처를 함께 담아보낸다.
이후 서버가 이 요청에 대한 응답을 할 때 응답 헤더의 Access-Control-Allow-Origin
이라는 값에 “이 리소스를 접근하는 것이 허용된 출처”를 내려주고, 이후 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin
을 비교해본 후 이 응답이 유효한 응답인지 아닌지를 결정한다.
Preflight Request
브라우저는 요청을 한번에 보내지 않고 예비 요청
과 본 요청
으로 나누어서 서버로 전송하는데 예비 요청
을 프리플라이트(Preflight Request)
라고 한다. 프리플라이트(Preflight Request)
에는 HTTP메소드 중 OPTIONS 메소드가 사용되며, 본 요청
을 보내기 전에 스스로 이 요청이 안전한지 확인하는 작업이다.
우리가 자바스크립트의 fetch API
를 사용하여 브라우저에게 리소스를 받아오라는 명령을 내리면 브라우저는 서버에게 예비 요청을 먼저 보내고, 서버는 이 예비 요청에 대한 응답으로 현재 자신이 어떤 것들을 허용하고, 어떤 것들을 금지하고 있는지에 대한 정보를 응답 헤더에 담아서 브라우저에게 다시 보내주게 된다.
이후 브라우저는 자신이 보낸 예비 요청과 서버가 응답에 담아준 허용 정책을 비교한 후, 이 요청을 보내는 것이 안전하다고 판단되면 같은 엔드포인트로 다시 본 요청을 보내게 된다. 이후 서버가 이 본 요청에 대한 응답을 하면 브라우저는 최종적으로 이 응답 데이터를 자바스크립트에게 넘겨준다.
이 플로우는 브라우저의 개발자 도구 콘솔에서도 간단하게 재현해볼 수 있는데, 필자의 블로그 환경에서 필자의 티스토리 블로그의 RSS 파일 리소스에 요청을 보내면 브라우저가 본 요청을 보내기 전에 OPTIONS 메소드를 사용하여 예비 요청을 보내는 것을 확인할 수 있다.
이 예비 요청에서 브라우저는 Access-Control-Request-Headers
를 사용하여 자신이 본 요청에서 Content-Type
헤더를 사용할 것을 알려주거나, Access-Control-Request-Method
를 사용하여 이후 GET 메소드를 사용할 것을 서버에게 미리 알려주고 있는 것이다.
https://evan-moon.github.io/2020/05/21/about-cors/
오늘은 CORS에 대해 알아봤다. 쉽게 정리하자면 SOP(Same-Origin Policy)라는 녀석 때문에 같은 출처에서만 공유가 가능한데, 예외적으로 CORS(Cross-Origin Resource Sharing) 다른 출처에서도 공유해주는 녀석! 이런 뜻인거 같다.
그 안에서도 CORS가 가능한지 아닌지 판독해주는 Access-Control-Allow-Origin
이 있다는 걸 알게되었다.
결국 CORS는 다른 도메인 간에도 자원을 공유할 수 있게 해주는 것! 이라고 정의 할 수 있고, 그 방법으로는 Access-Control-Allow-Origin
이라는 특정 헤더를 추가함으로써 동작할 수 있다.