1. CORS 란
프로젝트를 하면서 API 서버와 통신을 할 때 마주치게 되는 이슈 중의 하나가 이 CORS 정책 위반 에러다.
CORS는 Cross-Origin Resource Sharing 의 줄임말로, '교차 출처 리소스 공유' 라고 해석한다. 이렇게 단순히 직역을 하게 되면 무슨 의미인지 도통 감이 안오는데 내용을 자세히 알게되면 이 말을 충분히 이해할 수 있다.
우선 단어를 하나씩 쪼개서 알아보기로 하자.
1.1 Cross-Orgin 이라는 게 무슨 뜻이지?
우선 Origin은 출처인데, 이는 서버의 위치라고 생각할 수 있다. 즉 URL을 말하는 것이고, 이 URL은 Protocol과 Host, path와 포트 번호로 이루어져 있다.
포트 번호는 출처에서 생략이 가능한데, 이는 프로토콜의 기본 포트 번호가 정해져 있기 때문이다. 그러나 출처에 <https://test.com:4000> 이렇게 명시적으로 포트번호가 포함되어 있다면 이 포트번호까지 모두 일치해야 같은 출처라고 할 수 있다.
출처가 서로 일치하지 않는 다른 출처를 '교차 출처(Cross Origin)'라고 말한다. 바로 이 교차 출처가 CORS 정책의 핵심이다.
1.2 CORS 정책
웹에서는 다른 출처로의 리소스 요청을 제한하는 정책이 있는데, 이러한 방어막이 있음으로 우리의 리소스가 안전하다는 보장을 받을 수 있다. 이 정책으로는 2가지가 있는데, 하나는 CORS고 다른 하나는 SOP이다.
SOP은 Same-Origin Policy 로 해석 그대로 같은 출처에서만 리소스를 공유할 수 있다는 규칙의 정책이다. 하지만 실제적인 오픈스페이스 환경에서 다른 출처에 있는 리소스를 가져와서 사용하는 일은 굉장히 흔한 일이다. 그래서 몇가지 예외 조항을 두고 이 조항에 해당하는 리소스 요청은 출처가 달라도 허용하기로 했는데, 그 중 하나가 'CORS 정책을 지킨 리소스 요청'이다.
다른 출처로 자원을 요청하는 것은 SOP에 어긋나지만 예외 조항인 CORS 정책을 만족시킨다면 가능하다. 그러나 CORS 정책까지 지켜지지 않는다면 다른 출처의 자원은 아예 사용할 수 없게된다.
이러한 정책이 없다면 웹의 취약점을 파고들어서 웹사이트 사용자의 정보를 탈취하거나 비정상적인 기능을 수행하게 할 수도 있다.
1.3 출처를 구분하는 방법
같은 출처와 다른 출처를 구분하는 방법은 url의 구성 요소를 비교하는 방식이다. URL의 구성요소 중에 Scheme, Host, Port 이 3가지가 동일하면 된다.
Scheme은 http 또는 https 이고, Host 는 <http://test.com> 과 같은 웹 주소, Port는 주소 뒤에 :80 과 같은 번호다. 이렇게 3가지의 요소가 같다면 나머지는 다르더라도 같은 출처로 인정이 된다.
CORS는 브라우저에서의 정책이기 때문에 브라우저르 통하지 않고 서버간 통신을 할때는 이 정책이 적용되지 않는다.
2. CORS 이슈 해결하기
CORS 이슈가 무엇인지 알았다면, 실질적으로 이로인한 에러가 발생했을 경우 해결할 수 있는 방법을 알아보려 한다.
2.1 Access-Control-Allow-Origin 세팅
가장 대표적인 방법으로, 서버에서 Access-Control-Allow-Origin 헤더에 알맞은 값을 세팅해주는 것이다.
* 를 사용하여 세팅하면 모든 출처에서 오는 요청을 받는다는 의미로, 보안적으로 문제가 될수 있다. 따라서 정확한 출처를 명시해주는 것이 좋다.
CORS 관련 설정은 널리 알려진 백엔드 프레임워크에서는 라이브러리 등을 제공하고 있으므로 세팅 자체는 어렵지 않다.
2.2 Proxy 설정하기
프론트엔드 개발을 하다보면 CORS 에러를 자주 보게되는데, 백엔드에 이미 Access-Control-Allow-Origin 가 설정되어 있어도, [localhost](<http://localhost>) 출처는 넣지 않는 경우도 많기 때문이다.
이때는 웹팩에서 제공하는 프록시 기능을 사용하면 간단하게 CORS 에러를 해결할 수 있다.
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'https://api.test.com',
changeOrigin: true,
pathRewrite: {'^/api': ''},
}
}
}
}
위와 같이 설정을 해놓으면 로컬환경에서 /api 로 시작하는 요청에 대해 웹팩이 경로를 <https://api.test.com>로 프록싱해주기 때문에 CORS 정책을 지키면서 원하는 서버와 자유롭게 통신할 수 있다. 프록싱을 통해 CORS 정책을 우회할수 있는것이다.
그러나 어플리케이션을 빌드하고 서버에 올리고 나면 webpack-dev-server 가 구동하는 환경이 아니기 때문에, 실제 프로덕션 환경이 클라이언트 어플리케이션의 소스를 서빙하는 출처와 API 서버의 출처가 같은 경우에 사용하는 것이 좋다.
위의 두가지 방법으로 해결하는 것을 종합해봤을때, 결국은 프론트엔드 개발자가 마주하는 이 CORS 에러를 근본적으로 해결하기 위해 백엔드 개발자가 세팅을 해줘야 한다. 설정이 어려운 것은 아니므로 꽤나 쉽고 빠르게 문제를 해결할 수 있으니 해결 방법을 대략적으로 기억해두면 좋겠다.
'Computer Science' 카테고리의 다른 글
인증과 인가 (0) | 2021.08.12 |
---|---|
SPA (Single Page Application) (0) | 2021.06.23 |
JWT(Json Web Token) (0) | 2021.06.21 |
쿠키와 스토리지 (cookie & storage) (0) | 2021.06.20 |
TCP/ IP (0) | 2021.06.11 |