Home CORS
Post
Cancel

CORS

cors

SOP (Same Origin Policy)

SOP(동일 출처 정책)는 동일한 Origin에서만 나온 리소스와 상호작용하도록 하는 정책이다.

Origin?

이미지

오리진이란 위 그림에서 알 수 있듯 URL 요소 중에 protocol와 host(hostname + port) 부분을 가르켜 origin이라고하는데 이 부분이 일치해야 동일한 출처 즉 Same Origin이라고 판단한다. 참고로 IE(Internet Explorer)브라우저에서는 동일 출처인지 판단할 때 port를 끼워서 판단하지 않고 protocol과 hostname만을 가지고 판단한다.


보안을 위해서 동일한 origin에서 가져온 리소스만 사용한다는 것은 알겠는데 그럼 웹 개발을 할 때 origin에 있는 리소스가 필요한 상황에서는 어떻게 해야할까?

CORS (Cross Origin Resource Sharing)

CORS는 교차 출처 리소스 공유로 해석되며 추가 HTTP 헤더를 사용하여 다른 출처에서 가져온 리소스에 상호작용할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다.

CORS는 각각 Preflight Request, Simple Request, Credentialed Request 의 3가지 접근제어 시나리오가 존재한다.

Simple Request

클라이언트에서 서버로 보내는 요청이 다음과 같은 조건을 만족하면 해당 요청은 Simple Request가 된다.

옵션
MethodGET, HEAD, POST
HeadersAccept, Accept-Language, Content-Language, Content-Type
(헤더의 옵션 중) Content-Typeapplication/x-www-form-urlencoded, multipart/form-data, text/plain

이미지

위는 클라이언트의 요청이 Simple Request 로 제어될 경우의 흐름을 나타낸 그림이다. 이름처럼 단순하게 클라이언트에서 보낸 요청을 서버에서 받아 명시되어있는 Origin과 동일하면 클라이언트에게 응답을 보낸다.

표를 보면 알 수 있듯이 우리가 일반적으로 웹을 개발하며 API로 통신할 때 Content-Type이 대부분 json인 것을 생각하면 Simple Request로 제어되는 경우는 거의 없다고 보면되고 대부분은 아래에서 설명할 Preflight Request로 제어된다.

Preflight Request

이미지

Preflight Request는 OPTIONS 메서드를 가진 Preflight Request와 본 요청인 Main Request로 나뉘는데 Preflight Request를 보내서 해당 출처에서 서버와 상호작용 가능한지 확인하고 가능하다면 Main Request를 보내게된다.

Preflight Request로 Origin, 실제 요청의 메서드, 실제 요청의 추가 헤더등을 담아서 보내면

Preflight Response로 서버에서 허용하고있는 Origin들, 허용하는 메서드 허용하는 헤더, Preflight의 응답 캐시 기간(추후 같은 Preflight Request를 캐싱하는 기간)으로 응답한다.

왜 Simple Request로 하지않고 굳이 Preflight Request로 한 번의 과정을 더 거치게 되는걸까?

CORS 에러는 서버에서 내려주는 것이 아니라 서버에서 보낸 응답에 Allow-Origin을 보고 브라우저 단에서 발생시키는 에러다. 따라서 API 요청이 DB나 서버에 저장된 데이터를 변경시키는 요청일 경우 Preflight로 확인하지 않고 본 요청을 바로 보내게된다면 DB의 데이터는 수정되었지만 CORS 에러는 발생하는 상황이 발생한다.

이런 상황을 방지하기 위해서 Preflight Request로 허가된 출처, 메서드 등인지를 확인하는 것

Credentialed Request

인증관련 헤더를 포함할 때 제어되는 흐름, 쿠키나 jwt를 클라이언트에서 헤더에 포함시켜서 서버로 보내고 싶을 때 Credential 옵션을 주어야하는데 클라이언트에서만 이 옵션을 설정하게되면 서버에서는 이 값을 볼 수가 없기 때문에 서버에서도 Allow-Credentials 옵션을 설정해주어야한다.

Credentials 옵션을 설정할 때는 Allow-Origin 옵션에 와일드카드(*)를 사용할 수 없으니 주의하자.

해결하기

로컬일 경우 프론트 개발환경에서 webpack-server를 사용하고 있다면 프록시 설정을 해주어서 api 요청 서버를 속여서 cors 에러를 피해갈 수 있다.

하지만 실배포 환경일 경우에는 백엔드에서 설정을 해주는게 보편적인데 express 같은 경우에는 cors 라이브러리를 설치해서 손쉽게 해결할 수 있다.

https://velog.io/@minukang5874/URL-%EC%94%B9%EA%B3%A0-%EB%9C%AF%EA%B3%A0-%EB%A7%9B%EB%B3%B4%EA%B3%A0-%EC%A6%90%EA%B8%B0%EA%B8%B0

This post is licensed under CC BY 4.0 by the author.