Cross-Origin Resource Sharing (CORS) 개념 & 해결법
웹 개발자라면 한 번씩 신고식으로 보는 CORS(Cross-Origin Resource Sharing) 정책에 대해서 정리하려고 합니다.
위의 CORS policy 오류 메시지는 CORS 정책을 위반할 때 발생한다.
CORS (Cross-Origin Resource Sharing)
간단하게 브라우저에서 다른 출처의 리소스를 공유하는 방법이다.
요청 방식에 따른 CORS
1. HTML 태그
기본적으로 Cross-Origin 정책을 지원한다.
<script src="…"></script>
<link rel="stylesheet" href="…" />
<iframe src="…"></iframe>
<img class="" src="" alt="">
<video src="…"></video>
<audio src="…"></audio>
2.XMLHttpRequest, Fetch API 스크립트
기본적으로 Same-Origin 정책을 따른다.
다른 도메인의 소스에 대해 자바스크립트 API 호출하는 경우
웹은 크게 두가지의 Origin 정책을 가지고 있다. 그 중 첫번째가 SOP(Same-Origin Policy)이다.
브라우저는 서버로 요청을 보낼때 같은 출처인지 확인 하는데 이것이 SOP이다.
만약 다른 출처라면 브라우저는 다음에 설명할 CORS 정책을 따라 요청을 시도할 것이다.
확실히 알아야 할것은 출처를 비교하는 것은 서버의 역할이 아니고 브라우저가 하는 역할이다. 서버로 보내기전 브라우저에서 체크를 하는 것이다.
코드를 보면 이해하기 쉬울 것이다.
<body>
<img src="https://i.pinimg.com/564x/fd/ae/6d/fdae6d0d40fe58f28c356d398400591f.jpg" alt="이미지">
<script>
fetch('https://i.pinimg.com/564x/fd/ae/6d/fdae6d0d40fe58f28c356d398400591f.jpg')
.then(response => response.blob())
.then(imgBlob => {
const imageObjectURL = URL.createObjectURL(imgBlob);
const img = document.createElement('img');
img.src = imageObjectURL;
document.body.append(img);
})
</script>
</body>
개발자 도우의 Network 창을 보면 이미지를 img 태그로 한 번 fetch로 한 번, 총 두번 조회하였는데, fetch로 요청한 것의 상태 값이 CORS 오류인 걸 볼 수 있습니다.
https://i.pinimg.com/564x/fd/ae/6d/fdae6d0....jpg 'http://127.0.0.1:5500' 출처로 가져올 수 있는 액세스가 CORS 정책에 의해 차단되었습니다. 요청된 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다. 불투명한 응답이 필요에 적합한 경우, 요청 모드를 'no-cors'로 설정하여 CORS가 비활성화된 리소스를 가져오십시오.
위의 오류 코드를 해석 해보면 "Access-Control-Allow-Origin 헤더가 없습니다"에 주목할 필요가 있습니다.
츨처(Origin) 란?
우리는 사이트를 접속할 URL를 통해 접근하게 된다.
- 출처는 Protolcol, Host, Part 까지 합친 URL를 의미한다.
console.log(location.origin); // https://devlevel1.tistory.com
같은 출처와 다른 출처의 구분
기준 URL : https://tistory.com
URL | 같은 출처 | 이유 |
https://tistory.com/manage | O | Protocal, Host, Port 동일 |
https://tistory.com/manage?val=dev | O | Protocal, Host, Port 동일 |
https://tistory.com/manage#dev | O | Protocal, Host, Port 동일 |
http://tistory.com/manage | X | Protocal 다름 |
https://devlevel1.tistory.com/manage | X | Host 다름 |
https://tistory.com:81/manage | X | Port 다름 |
위의 내용을 보면 출처 구분을 하는데, 여기서 개발자들이 착각하는 부분이 출처 구분은 서버가 하는 것으로 오해하는 경우가 있는데, 서버가 아닌 브라우저에서 구분한다.
예로 Internet Explorer는 Port 정보를 아예 무시한다.
하지만 결국 해당 오류를 해결하기 위해서는 서버에서 Access-Control-Allow-Origin 헤더에 허용할 출처를 기재하여 클라이언트에 응답하면 되는 것이다.
추가로 요청을 같은 서버 단에서 처리하는 경우 CORS 에러와 만나지 않아도 된다.
해결 방법
Node.js 인 경우
var http = require('http');
const PORT = process.env.PORT || 3000;
var httpServer = http.createServer(function (request, response) {
// Setting up Headers
// * 모든 출처(orogin)을 허용
response.setHeader('Access-Control-Allow-origin', 'https://devlevel1.tistory.com');
// 모든 HTTP 메서드 허용
response.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// 클라이언트와 서버 간에 쿠키 주고받기 허용
response.setHeader('Access-Control-Allow-Credentials', 'true');
response.writeHead(200, { 'Content-Type': 'text/plain' });
response.end('ok');
});
httpServer.listen(PORT, () => {
console.log('Server is running at port 3000...');
});
AWS (S3 호스팅) 인 경우
S3 콘솔 메뉴에서 버킷 선택 > 권한 탭 선택 > 교차 출처 리소스 공유 창 편집 > JSON CORS 규칙 입력
[
{
"AllowedHeaders": [
"Authorization"
],
"AllowedMethods": [
"GET",
"HEAD"
],
"AllowedOrigins": [
"http://www.example.com"
],
"ExposeHeaders": [
"Access-Control-Allow-Origin"
]
}
]
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Cross-Origin Resource Sharing (CORS) - HTTP | MDN
Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources. CORS also relies on a mechanism by which
developer.mozilla.org
https://developer.mozilla.org/en-US/docs/Glossary/Origin
Origin - MDN Web Docs Glossary: Definitions of Web-related terms | MDN
Web content's origin is defined by the scheme (protocol), hostname (domain), and port of the URL used to access it. Two objects have the same origin only when the scheme, hostname, and port all match.
developer.mozilla.org
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
Same-origin policy - Security on the web | MDN
The same-origin policy is a critical security mechanism that restricts how a document or script loaded by one origin can interact with a resource from another origin.
developer.mozilla.org
https://developer.mozilla.org/ko/docs/Web/API/XMLHttpRequest
XMLHttpRequest - Web API | MDN
XMLHttpRequest (XHR) 객체는 서버와 상호작용할 때 사용합니다. XHR을 사용하면 페이지의 새로고침 없이도 URL에서 데이터를 가져올 수 있습니다. 이를 활용하면 사용자의 작업을 방해하지 않고 페이
developer.mozilla.org
https://developer.mozilla.org/ko/docs/Web/API/Fetch_API/Using_Fetch
Fetch API 사용하기 - Web API | MDN
Fetch API는 HTTP 파이프라인을 구성하는 요청과 응답 등의 요소를 JavaScript에서 접근하고 조작할 수 있는 인터페이스를 제공합니다. Fetch API가 제공하는 전역 fetch() 메서드로 네트워크의 리소스를
developer.mozilla.org