CORS 를 알아보자!

김하영·2023년 4월 22일
0

WEB

목록 보기
1/1

친구들과 진행하고 있는 토이 프로젝트의 아이디어 구체화 단계를 마무리하고 본격적으로 개발을 시작하게 되었다. 데이터 분석이 들어간 프로젝트이니 만큼 이번엔 백앤드 개발이 아닌 프론트앤드 개발로 프로젝트에 참여하고 있는데 FAST API로 구성한 API 서버에서 데이터를 받아오는 과정에서 다음과 같은 오류를 맞닥뜨리게 되었다.

Access to XMLHttpRequest at 'https://test.site/w1/indicator&team&2017' from origin 'https://test.site' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

이 오류는 뭐람...😂

분명 Insomnia를 사용해서 API 테스트를 했을때는 Response 200으로 정상 동작함을 확인했음에도 왜 이런 오류가 발생했는지 명확하게 알아두기 위해 이번 게시글을 작성하게 되었다.

CORS 란

Cross-Origin Resource Sharing의 줄임말로 교차 출처 리소스 공유라고 직역할 수 있다.
이렇게 번역된 말만 가지고 봤을때는 어떤 의미 인지 설명되기 어렵기 때문에 하나하나 다가가보고자 한다.

Origin(출처)

어떤 사이트를 방문하고자 할때는 인터넷 주소창에 URL이라는 문자열을 통해 접근하게 된다.
URL은 하나의 문자열 같지만 사실은 다음과 같이 여러개의 구성 요소로 이루어져 있다.

여기서 Origin은 Protocol + Host + Port가 결합된 URL이라고 보면 된다. (위 경우에는 Port가 생략됨)
간단하게 자바스크립트로도 현재 사이트의 Origin을 알아낼 수도 있다.

console.log(location.origin);

출처의 동일함은 URL의 구성 요소 중 Protocol + Host + Port 가 동일하면 동일 출처로 판단하게 된다.

SOP(Same Origin Policy)

▶︎ 동일한 출처에서만 리소스 공유 가능 즉, 다른 출처(Cross-Origin) 서버에 있는 리소스는 상호작용이 불가능.

서로 다른 출처를 가진 두 어플리케이션이 자유롭게 리소스를 주고 받을 수 있는 환경에서는 CSFR(Cross-Site Request Forgery)나 XSS(Cross-Site Scripting) 등의 방법을 이용해서 해커가 개인 정보를 가로챌 수 있는 가능성이 존재한다.

이런 악의적인 경우를 방지하기 위해 SOP 정책으로 동일하지 않는 다른 출처의 스크립트가 실행되지 않도록 브라우저 단에서 방지하게 된다.

출처 비교와 차단을 브라우저가 하기 때문에 서버 에러로 착각하기 쉽다.
현재 구성중인 서비스는 Backend(API) 서버와 Frontend 서버가 분리되어 있기 때문에 insomnia로 호출했을때 정상적으로 반환된 데이터가 실행중인 Frontend에서 Axios로 API를 호출했을때 CORS 오류가 발생했던 것이다!

현실적으로 SOP만을 적용해서 서비스를 제공하기에는 어려움이 존재하기 때문에 몇가지 예외 조항을 두고 Cross-Origin도 허용하도록 한 것이 CORS이다.

CORS 동작 프로세스

  1. 클라이언트에서 HTTP 요청의 헤더에 Origin을 담아 전달
  2. 서버는 응답헤더에 Access-Control-Allow-Origin을 담아 클라이언트로 전달
  3. 클라이언트에서 Origin과 서버가 보내준 Access-Control-Allow-Origin을 비교
    3-1. 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin을 비교해본 후 차단 여부를 결정
    3-2. 만약 유효하지 않다면 그 응답을 사용하지 않고 버린다 👉🏻 CORS 에러

마무리

CORS가 동작하는 프로세스를 살펴보면 결국 서버에서 허용하는 Origin(URL)을 알고 있다면 CORS 에러는 발생하지 않게 된다는 점을 알 수 있었다.

API 구성 코드에 아래와 같은 코드를 추가하여 간단하게 해결하였다.

...
# CORS 오류 방지를 위한 Origin 정보 등록
from starlette.middleware.cors import CORSMiddleware

origins = [
    "test.site.com" 
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
...

그동안 개발에서 잠깐 멀어진 생활을 하다보니 이렇게 쉽게 해결할 수 있는 문제들도 마냥 어렵게만 느껴지는 것 같다.
남은 휴직 기간동안 이 토이 프로젝트를 진행하면서 부족한 부분들을 기록으로 남기면서 다시 개발에 재미를 느끼고 싶다.

profile
성장하는 개발자

0개의 댓글