CORS 에러 파보기

Daon (HyeongIk Jo)·2024년 7월 31일
2

개글스

목록 보기
8/8

위 글은 발표 자료를 제작하며 알게된 내용을 정리한 글입니다.

개발자를 꿈꾸는 이들이 처음 웹 협업 프로젝트를 경험하다 보면 한번씩 겪게 되는 상황이 있다.

바로 CORS ERROR이다. 이 에러에 대해 알아보자.

SOP 와 CORS

CORS를 알기 위해선 SOP의 개념을 함께 이해하는 것이 좋다.

SOP (Same Origin Policy)

동일 출처 정책

CORS (Cross Origin Resource Sharing)

교차 출처 자원 공유

두 개념의 직역을 나열해보아도 무슨 뜻 한번에 이해하기 어렵다.
두 단어에 공통적으로 있는 Origin을 먼저 알아보자.

Origin

Origin(출처)란 서버의 위치를 식별하기 위해 필요한 최소한의 요소들이다.

위 그림과 같이 스킴, 호스트명, 포트 3 가지 요소를 묶어 Origin이라 정의한다.
이를 기반으로 SOP와 CORS에 대해 깊이 알아보자.

SOP

동일 출처 정책이란 동일한 출처 간의 자원 공유만 허용하는 브라우저의 정책이다.

예를 들어, 위와 같은 상황이 존재한다면 웹 서버가 데이터 처리를 API 서버 위임했다면 브라우저는 두 출처가 다름을 인식하고 Error를 발생시키게 된다.

생겨난 이유

이러한 브라우저 정책은 보안적인 이슈(CSRF, XSS 등) 예방하기 위해 적용되었다.

CORS

생겨난 이유

웹이 발전하면서 Web 서버와 API 서버가 분리되는 것이 자연스러워졌고 이를 위해 SOP의 예외 조항인 CORS가 대응법으로 사용하게 되었다.

개념

교차 출처 자원 공유란 서버에 명시되어 있는 출처들에 한해 자원 공유를 허용하는 정책입니다.

위와 같이 API Server 에 Web Server에 해당하는 출처를 명시하면 브라우저가 예외적으로 자원 공유를 허용하는 것이다.

개념을 알았으니 동작하는 방식을 한번 알아보자.

CORS 동작 방식

CORS 기본 동작 방식

브라우저가 CORS 여부를 판단하는 방식은 다음과 같다.

GET /profile HTTP/1.1

Origin: http://daon-world.com

먼저 Client 측에서 자신의 출처를 Origin 헤더에 담아 HTTP Request를 보낸다.

HTTP/1.1 200 OK

Access-Control-Allow-Origin: http://daon-world.com

Server는 자신의 허용 목록에 담긴 출처들을Access-Control-Allow-Origin 헤더에 담아 응답한다.

브라우저는 이 두 헤더의 값이 다른 경우 CORS 에러를 반환한다.

CORS 시나리오

브라우저가 CORS를 동작하는 여러 매커니즘 중 대표적인 3가지만 다뤄보려 한다.

Simple Request(단순 요청)

우선 Simple Request이다. 해당 용어는 CORS spec에서만 쓰이는 용어이나 편의를 위해 사용하겠다.

Simple Request는 위에서 설명한 기본 동작 원리를 바탕으로 동작한다.
단, 아래 조건모두 만족해야 가능하게 설정되어 있다.

  1. 3가지 메서드만 허용된다. (GET, POST, HEAD)
  2. 자동으로 설정되는 헤더를 제외하고 수동으로 설정할 수 있는 헤더는 Fetch 사양에서 CORS 허용 목록에 있는 요청 헤더로 정의된 헤더만 허용된다
  3. Content-Type 헤더에 지정된 미디어 유형은 지정된 것만 허용된다.
    (application/x-www-form-urlencoded, multipart/form-data, text/plain)
    ...
    - Cross Origin Resource Sharing - MDN

Preflight Request(사전 요청)

Simple Request는 브라우저가 서버의 응답 헤더를 확인 후 출처가 같은지 판단한다. 이 과정에서 서버는 응답을 반환해야 하기 때문에 CORS ERROR가 발생하기 전 실제 데이터를 처리하게 된다.
이를 방지하기 위해 대부분의 요청은Preflight Request 시나리오를 따르게 된다.

이 사니라오는 사전에 서버에 어떠한 영향도 주지 않는 안전한 HTTP 메서드인 OPTIONS를 이용하여 미리 요청/응답을 통해 출처가 같은지 판단한다.

이후 출처가 같다면 본 요청을 다시 보내어 실제 요청을 처리한다.

특징

  • 서버의 출처 목록에 *란 와일드 카드를 쓸 수 있다.
    - 해당 와일드 카드는 모든 출처에 한하여 요청을 허용함을 뜻한다.

Credentialed Request(인증 요청)

기본적으로 브라우저는 쿠키와 같은 인증정보를 헤더를 담지 않는다. 이때 쿠키를 요청에 보내기 위해 client 측 fetch() 내부에 credentials: "include" 설정을 추가하게 된다면 Credentialed Request 시나리오를 따르게 된다.

const request = new Request(url, { credentials: "include" });

const fetchPromise = fetch(request);
fetchPromise.then((response) => console.log(response));

다른점

  1. HTTP 요청 헤더에 Cookie와 같은 인증 값을 추가할 수 있다.
  2. 서버는 출처와 함께 인증 정보를 다룰 출처임을 명시하는 Access-Control-Allow-Credentials: true 설정을 추가해 주어야 한다.

마무리

MDN에 정의되어 있는 CORS를 알아야 하는 대상들을 찾아보면 웹 프로젝트 관련 모든 이해관계자들이라 설명한다.
따라서 위에서 설명한 방식 여러번 숙지하며 언제든 빠르게 대처할 수 있는 개발자로 성장하길 바란다.


참고 문헌

profile
To be a Backend Developer

0개의 댓글

관련 채용 정보