CORS

CORS 정책 / 동작 방식 / HTTP 요청-응답 흐름 / CORS 해결 방법

2022-02-13에 씀

CORS: 교차 출처 리소스 공유 (Cross-Origin Resource Sharing)

스크린샷 2021-10-28 오후 2 41 48

CORS 정책

SOP (Same-Origin Policy)

CORS

쓰는 이유

CORS의 동작

CORS 동작 방식에는 세 가지의 시나리오가 있다

CORS 에러 경험해보기

1const headers = new Headers({
2'Content-Type': 'text/xml',
3});
4fetch('https://github.com/ooooorobo', { headers });

기본 흐름

  1. 클라 ⇒ 서버: HTTP 요청 헤더 Origin 필드에 요청 출처를 담는다
  2. 서버 ⇒ 클라: HTTP 응답 헤더 Access-Control-Allow-Origin 필드에 이 리소스에 접근이 허용된 출처를 담아서 보낸다
  3. 브라우저는 요청의 Origin과 응답의 Access-Control-Allow-Origin을 비교하고 응답의 유효 여부를 결정한다.
  4. 응답이 유효하지 않다고 판단하면 CORS 에러가 발생한다.

개발자 도구 콘솔 탭과 네트워크 탭에서 CORS error 메시지를 볼 수 있다.

1. Preflight Request

  1. 클라 ⇒ 서버: 본 요청을 보내려는 URI에 Option 메소드(Preflight) 요청을 보낸다.
1// 본 요청
2const headers = new Headers({
3'Content-Type': 'text/xml',
4});
5fetch('https://roborobo.tistory.com', { headers });
1...
2Access-Control-Request-Headers: content-type
3Access-Control-Request-Method: GET
4Connection: keep-alive
5Host: roborobo.tistory.com
6Origin: https://www.naver.com
7Referer: https://www.naver.com/
8...
  1. 서버 ⇒ 클라: 서버의 CORS 정책에 따라 Preflight에 대해 메소드, 헤더, 쿠키 등의 허용 여부에 대해 응답
1Access-Control-Allow-Origin: https://roborobo.tistory.com
2Content-Encoding: gzip
3Content-Length: 5060
4Content-Type: text/html; charset=utf-8
5Date: Thu, 28 Oct 2021 05:08:23 GMT
6P3P: CP='ALL DSP COR MON LAW OUR LEG DEL'
7Vary: Accept-Encoding
8X-UA-Compatible: IE=Edge

2. Simple Request

  1. 클라 ⇒ 서버: 예비 요청을 보내지 않고 바로 본 요청을 보낸다.
  2. 서버 ⇒ 클라: 응답 헤더에 Access-Control-Allow-Origin 값 등을 보낸다.
  3. 브라우저가 CORS 정책 위반 여부를 검사한다.
  1. 요청 메소드가 GET, HEAD, POST 중 하나
  2. AcceptAccept-LanguageContent-LanguageContent-TypeDPRDownlinkSave-DataViewport-Width, **Width**를 제외한 헤더를 사용하면 안된다.
  3. 만약 **Content-Type**를 사용하는 경우에는 application/x-www-form-urlencodedmultipart/form-data, **text/plain**만 허용된다.

3. Credentialed Request

CORS 해결 방법

  1. 동일 출처 사용하기
  2. 서버에서 Access-Control-Allow-Origin 세팅
  1. 프록시 서버 사용

1module.exports = {
2 devServer: {
3 proxy: {
4 '/api': {
5 target: 'https://domain.com',
6 changeOrigin: true,
7 pathRewrite: { '^/api': '' },
8 },
9 }
10 }
11}
12
13// 혹은 package.json에서
14{
15 ...
16 "proxy" : "https://api.domain.com"
17 ...
18}

참고

프로필 사진

조예진

이전 포스트
웹의 동작 방식 - 주소창에 사이트 주소를 입력하면 일어나는 일
다음 포스트
SourceTree에서 Unity 씬, 프리팹 병합을 위한 UnityYAMLMerge 설정