SKUPLATE를 배포하고 Mixed Content 에러까지 해결한 이후에는 CORS 정책 문제로 브라우저 콘솔이 다시 한 번 빨개졌었다.
물론 데이터 역시 뜨지도 않았다. 이 프로젝트에서만 만났으면 문제가 없었을텐데, 이후에 MLOps 프로젝트, 온라인 서점 프로젝트, 심지어 이 블로그를 재배포한 오늘, 또 마주했다.
Access to XMLHttpRequest at 'https://AWS에서-받은-SKUPLATE-백엔드-인스턴스-도메인'
from origin 'https://www.skuplate.com' has been blocked
by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
당시 마주했던 에러 문구이다.
내가 요청한 리소스에 대해서, 즉, 서버로부터 받은 응답에서 브라우저가 Access-Control-Allow-Origin 헤더가 찾지 못했으니 차단했다고 알려주는 것이다.
다시 말하자면 "백엔드에서 프론트엔드 서버에 대한 접근 허가를 하사하지 아니 했으니 찾지 말라는 것"
둘 다 내가 배포했는데, 이런 말을 들으니 억울했었다.
먼저, Same-Origin Policy를 살짝이라도 알아야 한다. 이는 브라우저의 동일 출처 정책으로, 다른 출처에서 데이터 접근을 하려고 하면 해당 접근을 차단하는 것이다. 절대로.
악성 사이트가 사용자 데이터(쿠키 등)에 무단으로 접근하는 것을 막으려고 설계되었다고 한다.
CORS 정책은 Cross Origin Resource Sharing의 약자로, 브라우저에서 서로 다른 출처(Origin) 간의 리소스 공유를 허용하거나 제한하는 것이다.
SOP와 비슷한 역할이긴 하나, SOP의 제한보다는 완화된 것을 볼 수 있다.
출처 Origin
여기서 출처(Origin)은 인터넷 상에서, 요청을 보낸 원서버, 그 요청을 받는 원서버를 말한다. 네트워크 상에서 전달해주는 서버들은 가리키지 않는다. 이 Origin은 URL의 Protocol, Host, Port를 조합하여 정의하기에 출처를 비교한다는 것은 이 값들을 비교한다는 것이다.
하나라도 다르면, 그 둘은 다른 출처로 간주한다.
ex) https(protocol) + www.skuplate.com(host) + 443(port)
Mixed Content 에러가 발생했을 때도 CORS 에러는 발생했었다. 도메인도 다르고, 프로토콜도 달랐기에...
CORS 정책이 필요한 이유
Simple Request와 Preflight Request의 조건을 비교해보면 Preflight Request를 통해서 사용자의 민감한 데이터가 털릴 위험이 더 높은 것에 재차 요청 검토를 통해 보안을 강화하고 있다.
Access-Control-Allow-Origin: https://skuplate.com*이라고 해두면, 들어오는 요청 그대로 모두 다 허용하는 것이다Access-Control-Allow-Methods: GET, POST, DELETEAccess-Control-Allow-Headers: Content-Type, AuthorizationAccess-Control-Allow-Credentials: true프론트엔드는 도메인을 적용하여 https://www.skuplate.com 인 반면 백엔드는 도메인을 또 살 필요 없겠다 싶어 AWS에서 준 그대로 aws-ec2.pacific.titanic-31svad4938uf.com(대충 이런 느낌이었던...) 사용했었다.
그래서 다음과 같이 백엔드(Express)에서 Access-Control-Allow-Origin 설정을 추가하여 CORS 정책에 위반되지 않도록 하여 문제를 해결하였다.
const corsOptions = {
origin: 'https://skuplate.com',
credentials: true,
};
app.use(cors(corsOptions));
백엔드에서 CORS 관련 설정을 하더라도 CORS 정책 문제를 언제든지 만날 수 있다. 😭
Access to XMLHttpRequest at 'https://api.monte-log.com/posts?page=1&limit=7'
from origin 'https://www.monte-log.com' has been blocked
by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
이 블로그를 배포하면서 마주했던 에러 문구인데, 아이러니하게도 나는 백엔드 코드를 작성하면서 가장 먼저 했던 일이 CORS 정책 설정이었다.
처음 배포했을 때부터 발생한 에러는 아니었기에 더 당황스러웠었다. CORS 정책과 관련된 문제였으면 진작 터졌어야하는데 잘 지내다가 CORS 에러 문구를 띄우니까!!!
알고보니 서버로 요청을 보내고 받은 응답에 브라우저가 Access-Control-Allow-Origin 헤더를 찾지 못한 것이 문제였다.
헤더 설정을 안 했나? 아니다.
백엔드 코드가 build는 성공했지만, runtime 에러가 있었고, 배포를 하고 블로그를 실행시켰을 때, 서버에서 응답이 돌아오지 않으니 Access-Control-Allow-Origin 헤더도 오지 못한 것이다.
이 헤더가 없으니 CORS 정책 또한 위반된 것.
CORS 정책, 내 서버를 지키기 위해 있는 것.
누군가 함부로 내 서버에 접근하지 못하도록 함과 동시에 내가 친하게 지내고 싶은 서버와만 연락할 수 있도록 하는 것.
CORS 에러가 떴을 때, CORS 관련 설정값들만 보지 말고, 서버가 응답을 보내긴 하는지도 확인해보자!
참고 및 출처
https://velog.io/@effirin/CORS%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80