preflight라고도 불리는 OPTIONS 요청은 브라우저가 서버에게 지원하는 옵션들을 미리 요청하고 허가된 요청에 한해서 전송하기 위한 보안상의 목적이 있다.
모든 경우에 발생하지 않고, 실제 요청에 비해 많은 부분을 차지하지 않지만 경우에 따라 수백 ms 응답 속도가 중요하다면 발생하지 않도록 하는 것이 좋다. 그러기 위해선 발생하는 상황을 알아야 하는데 이는 CORS와 관련이 있다
CORS란?
HTTP header에 추가적인 정보를 추가하여 현재 웹페이지가 웹페이지를 받은 서버(자기 자신)뿐만 아니라
다른 서버에서 요청한 정보도 허용할 수 있도록 해주는 것이다
대표적인 예로 CDN의 이미지를 사용하거나
현재 웹서버(네이버)와 분리되어 있는 API 서버(기상청)로 요청을 보낼 때 사용한다
<img src ='<cdn-url>/image.png'>
예를 들어 네이버 웹사이트가 기상청 서버의 자원을 사용하고 싶다면
기상청 서버에 자신(네이버)이 요청을 보내도 되는지 물어봐야 한다
물어보는 과정을 pre-flight 라고 부른다
1 네이버에서 기상청에게 요청을 보낼 때 http header에 {Origin : naver.com} 으로 요청하는 출처를 적어준다
2 서버가 응답을 보낼때 http header에 { Access-Control-Allow-Origin : 허용하는 주소 } 로 CORS 를 허용할 URI 을 명시해준다
3 브라우저는 해당 http header를 해석하여 요청을 승인할지 거부할지 판단한다
4 브라우저가 승인하면 비로소 본래 하려던 요청을 서버에 보낸다
위의 pre-flight 절차에서 서버에게 요청할 때 사용하는 HTTP 메소드가 OPTIONS 메소드 이다
cors는 유용하지만 보안상의 문제점을 가지고 있는데
웹사이트에서 악의적인 목적으로 외부로 정보를 보내는 것과 같은 요청을 보낼 수 있기 때문이다
그렇기 때문에 브라우저는 OPTIONS를 사전요청(preflight)해서 서버에서 허용하는 옵션을 미리 확인하고
허용되지 않은 요청의 경우 405(Method Not Allowed)에러를 발생시키고 실제 요청은 전송하지 않는다
3가지 조건을 모두 만족하면 pre-flight 과정 없이 요청을 보낼 수 있다
1 GET
, HEAD
, POST
요청 중 하나
2 user agent에 의해 자동으로 설정되는(Connection, User-Agent, Fetch 스펙상 forbidden header로 정의되어 있는) 헤더외에 CORS-safelisted request-header로 명시된 헤더들만 포함된 경우(Accept
, Accept-Language
, Content-Language
, Content-Type
등)
3 Content-Type은 application/x-www-form-urlencoded
, multipart/form-data
, text/plain
만 허용