개발하면서 한번쯤은 CORS에러를 마주쳤을 것이다.
Access-Control-Allow-Origin 헤더가 없다는 메시지와 함께 데이터가 오지 않아 답답했던 경험이 있을 것이다.
CORS가 무엇이고, 왜 존재하며, 에러가 발생했을 때 두려움을 느끼지 않고자 이 글을 쓴다.
CORS(Cross-Origin Resource Sharing)
origin (출처)
URL의 프로토콜, 호스트, 포트 3가지를 조합한 것
모두 같으면 출처가 같다, 하나라도 다르면 출처가 다르다고 표현한다.
Cross-Origin Request (교차 출처 요청)
다른 출처의 자원을 사용하기 위해 네트워크 요청을 만드는 것
Same-Origin Policy (동일 출처 정책) 으로 브라우저는 실행 중인 애플리케이션의 출처와 다른 출처의 자원을 요청하면 이를 차단한다.
이를 허용하려면 서버와 약속 - CORS를 해야한다.
CORS의 동작 원리
3000 번 포트에서 3001번 포트로 응답을 보내고 받게한다.
tsx
// index.html<body> <script> const init = async () => { // 3001번 포트에서 데이터 가져오기 const response = await fetch("http://localhost:3001/resource.json"); const data = await response.text(); const jsonElement = document.createElement("pre"); jsonElement.textContent = data; document.body.appendChild(jsonElement); }; // DOM 로드 완료 후 init 함수 실행 document.addEventListener("DOMContentLoaded", init); </script> </body>
사전 요청 (Preflight Request)
단순한 요청에 해당하는 GET, POST, HEAD 메소드가 아닌 PUT, PATCH, DELETE 메소드를 사용하는 경우
서버는 요청을 보낸 측이 브라우저가 아닐 수도 있다고 판단한다.
따라서 브라우저와 서버는 서로를 확인하기 위한 **사전 요청(Preflight Request)**을 먼저 주고받는다.
브라우저에서 동작하는 스크립트의 메소드를 PUT으로 변경해보자:
요청 헤더: Access-Control-Request-Method에 사용하려는 메소드(PUT)를 명시
브라우저는 “교차 출처로 PUT 메소드를 사용해도 되나요?”라고 서버에게 먼저 확인하는 것이다.
서버가 다른 출처에서 PUT 메소드를 허용하려면 Access-Control-Allow-Methods 응답 헤더를 설정해야 한다: