CORS란?
01. CORS(Cross-Origin Resource Sharing) 개요
CORS란 직역하면 교차 출처 리소스 공유라고 하며, 브라우저에서 다른 출처의 리소스를 공유하는 방법을 말한다.
CORS에 대해 이해하려면 그 전에 먼저 웹 보안 정책중 하나인 SOP(Single-Origin Policy)에 대해 알아야한다. SOP란 2011년 처음 등장한 보안 정책으로, 같은 출처에서만 리소스를 공유할 수 있게끔 정해둔 규칙이다. 클라이언트 어플리케이션은 코드를 열어 확인해보는것이 쉬운 구조로 되어있다. 특히 웹은 브라우저에서 개발자도구를 열어보기만 해도 거의 대부분의 코드들이 노출된다. 이런 경우 CSRF(Cross-Site Request Forgery)
, XSS(Cross-Site Scripting)
등의 방법으로 마치 정상적인 클라이언트인양 위장하여 사용자 정보를 탈취하는 등의 공격에 매우 쉽게 당할 수 있다. 때문에 웹은 기본적으로 같은 출처에서만 리소스를 공유할 수 있게 하였다.
그러나 웹 어플리케이션을 개발하다보면 다른 출처의 리소스를 가져와서 사용하는 경우가 매우 많다. 이러한 경우를 위해 몇가지 예외조항을 두고, 이 조항에 해당하는 경우에는 출처가 다르더라도 리소스를 공유해도 되게 하였으며, 그 조항중 하나가 바로 CORS 정책을 지킨 다른 출처에서의 리소스 요청이다.
02. 출처(Origin)
출처(Origin)란, URL에서 Protocol, Host, Port까지 모두 합친것을 출처라고 부른다. 예를 들어 현재 웹페이지의 주소가 https://seoplee.tistory.com/category/Network
일 때 출처가 같은지를 구분하는것은 다음과 같다.
URL | 같은 출처 | 이유 |
https://seoplee.tistory.com/60 | O | Protocol, Host, Port가 동일 |
http://seoplee.tistory.com/60 | X | Protocol이 다름 |
https://tistory.com | X | Host가 다름 |
https://seoplee.tistory.com:81 | ? | 브라우저마다 다름 |
마지막의 경우, 원 출처 https://seoplee.tistory.com/category/Network 에 포트번호를 명시하지 않았기 때문에, 브라우저의 독자적인 출처 비교 로직을 따른다. (원 출처에 포트번호가 명시되어있다면 포트번호가 다를경우 반드시 다른 출처이다.)
03. CORS 동작
기본적으로 웹 어플리케이션에서 다른 출처의 리소스를 요청할 때, HTTP를 사용하여 헤더에 Origin 필드를 추가하여 출처를 함께 담아 보낸다. 이후 서버가 이 요청에 대한 응답을 할 때 응답 헤더의 Access-Control-Allow-Origin 필드에 허용된 출처를 보내주고, 응답을 받은 브라우저는 보냈던 Origin과 응답의 Access-Control-Allow-Origin 값을 비교하여 유효한지 결정한다. 이 때 CORS는 크게 두가지 방식으로 동작한다.
Simple Request
서버에 본 요청을 바로 보내는 방법.
Simple Request의 조건은 다음과 같으며 이를 모두 만족해야 Simple Request로 요청한다.
- 요청 메서드가
GET
,POST
,HEAD
중 하나여야 한다. Accept
,Accept-Language
,Content-Language
,Content-Type
,DPR
,Downlink
,Save-Data
,Viewport-Width
,Width
를 제외한 헤더는 사용하면 안된다.- Content-Type 헤더는
application/x-www-form-urlencoded
,multipart/form-data
,text/plain
중 하나를 사용해야 한다.
위 조건중 특히 2,3번 조건을 만족하는지 주의해야 한다. 흔히 Authorization
헤더를 자주 사용하는데, 이는 2번 조건에 만족하지 않으니 주의해야한다. 또 많은 REST API들은 Content-Type으로 application/json
을 사용하기 때문에 3번 조건을 만족하기 어렵다.
Preflight Request
서버에 예비 요청을 보내서 안전한지 판단한 후, 본 요청을 보내는 방법. 일반적으로 가장 많이 사용된다.
예비요청은 OPTIONS
메서드로 서버에 먼저 요청하여 본 요청을 전송할지 판단한다. Preflight Request를 수행할 때, 요청 헤더에는 Origin 외에도 본 요청에서 어떤 메소드를 사용할지를 알려주는 Access-Control-Request-Method
필드와, 본 요청에서 어떤 헤더를 사용할지를 알려주는 Access-Control-Request-Headers
필드가 존재한다. 서버는 이 예비 요청에 대한 응답으로 Access-Control-Allow-Origin
헤더를 포함한 응답을 브라우저에 보내주고, 브라우저가 다시 이 헤더를 확인하여 유효한 응답인지 결정 후 본 요청을 진행한다.
Reference
'WEB' 카테고리의 다른 글
[React] useState의 동작원리에 관하여 (0) | 2022.12.28 |
---|---|
next-sitemap을 사용하여 동적 생성 페이지 sitemap 생성하기 (0) | 2022.12.19 |
DOM(Document Object Model) (0) | 2022.06.27 |
CSS em & rem (0) | 2022.06.26 |
JavaScript 기본 동작 원리 (with Stack, Queue, Event Loop) (0) | 2022.06.25 |