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

YiJaeE·2021년 2월 7일
post-thumbnail

CORS란 Cross-Origin Resource Sharing의 약자로, 교차 출처 리소스 공유라고 불리는 HTTP 헤더 기반 메커니즘이다. 이렇게만 봐서는 그래서 무슨 역할을 하는 것인지 알기가 쉽지 않다. 쉽게 말하면, CORS는 브라우저가 안전한 리소스만을 골라내어 웹을 사용할 수 있도록 하는 것을 말한다.

브라우저는 왜 안전한 리소스만을 골라내려고 하는 걸까?

설치형 어플과 달리 웹은 개발자 도구를 열면 html, css, Javascript까지 모든 코드를 확인할 수 있는 경우가 많다. 웹은 누구나 이용하는 것이고, 개발자 도구 역시 누구나 열어볼 수 있기 때문에 프레임워크나 라이브러리를 사용하지 않은 경우 해당 웹을 구성하는 코드를 거의 다 확인할 수 있다. 누구나 확인할 수 있다는 것은 그만큼 공격에 취약해진다는 뜻으로, 실제로 Javascript의 경우 CSRF(사이트간 요청 위조: Cross-Site Request Forgery)나 XSS(사이트간 스크립팅: Cross-Site Scripting)와 같은 방식으로 웹이 공격받을 가능성이 커진다.

이런 보안상의 이유로 브라우저는 스크립트에서 시작된 교차 출처 HTTP 요청을 제한한다. 특히 XMLHttpRequest 및 Fetch API는 동일 출처 정책(SOP)을 따르는 대표적인 예다.

브라우저가 출처를 판단하는 방법

브라우저가 서버에 리소스 요청을 보낼 때 요청 헤더의 Origin이라는 필드에 요청을 보내는 출처를 담아서 보낸다. 리소스 요청을 받은 서버에서는 응답 헤더의 Access-Control-Allow-Origin에 접근이 허용된 출처를 함께 담아서 리소스를 보내야 한다. 리소스를 받은 브라우저는 자신이 보냈던 Origin과 서버가 보낸 Access-Control-Allow-Origin을 비교해 값이 같은 경우 SOP을 따르기 때문에 안전한 리소스라고 판단한다. 만약 교차 출처를 사용할 경우 CORS 정책을 위반하지 않는 올바른 CORS 헤더를 포함해야 하는데, 이를 위반하면 CORS 에러를 만나게 되는 것이다.

브라우저가 보냈던 Origin과 서버가 보낸 Access-Control-Allow-Origin을 비교하는 방법은 비교적 단순하다. scheme, host, port가 동일한지를 기준으로 삼는다.

scheme: http, https
host: google.com 등
port: 80, 3000 등

단, scheme과 host가 다르면 무조건 교차 출처로 간주되지만 port가 다른 경우는 대상 브라우저의 정책에 따라 교차 출처로 볼지, 동일 출처로 볼지 판단한다.

결국 교차 출처로 간주된 경우, 교차 출처이지만 Access-Control-Allow-Origin에 접근이 허용된 출처를 포함하고 있냐 아니냐에 따라 접근이 가능할 수도 있고 브라우저가 접근을 차단하며 CORS 에러를 발생시킬 수도 있다.

CORS 에러 해결하기

1. Access-Control-Allow-Origin에 접근이 허용된 출처를 명시

Access-Control-Allow-Origin 세팅 서버에서 Access-Control-Allow-Origin에 출처를 명시해준다. *를 사용하면 모든 출처를 허용할 수 있으나 보안상 권장되지 않는 방식이다. 그도 그럴 것이 *를 사용해서 모든 출처를 허용하는 건 CORS 정책에 맞게 에러를 해결하는 방식이라기보다는 정책을 위반하는 것에 가깝기 때문이다.

2. (개발시) 프록시를 사용해서 CORS 우회

Webpack Dev Server 프록시 설정 로컬에서 프론트엔드 개발을 하는 경우 프록시로 CORS 정책을 우회할 수 있다. CORS 정책을 지킨 것처럼 브라우저를 속이면서 개발을 하는 방법인데, 개발 단계에서는 사용하기 용이한 방법이지만 빌드 후에도 이 방법을 사용할 수는 없다.


CORS는 왜 이렇게 우리를 힘들게 하는걸까?

profile
개발을 개발개발 🐾

0개의 댓글