문제 상황
위와 같은 html 파일을 로컬환경에서 크롬 브라우져로 실행시켰더니
다음과 같이 에러 발생
에러 메시지 설명
Access to script at 'file:///C:/경로/js/module.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.
- file://: 로컬 파일 시스템에서 로드하려고 시도함.
- origin 'null': 로컬 파일 시스템에서의 출처는 null로 간주됨.
- CORS policy: 다른 출처의 리소스에 접근할 때 CORS 정책에 의해 차단됨.
- 지원되는 프로토콜: http, https, data 등 프로토콜을 통해서만 접근이 허용됨.
왜?
매번 'CORS 란게 있구나' 정도로 넘어갔기 때문에 이번 기회에 제대로 한번 알아봐야 겠다고 생각.
일단 핵심은 브라우저 보안 정책인 동일 출처 정책(SOP) 때문
동일 출처 정책 (SOP):란?
브라우저는 보안을 위해 동일 출처 정책(Same-Origin Policy, SOP)을 사용함.
이 정책은 한 출처(origin)에서 불러온 문서나 스크립트가 다른 출처에서 불러온 리소스와 상호작용하는 것을 제한함.
이를 통해 악성 스크립트가 사용자의 데이터를 훔치거나 변경하는 것을 방지하기 위함.
이때 출처를 구분하는 기준은 URI의 `프로토콜, 호스트, 포트`가 같은가를 통해 구분한다.
참고) 일반적인 HTTP(S) URL의 구성 요소
예: http://www.example.com:80/path/to/file.html
protocol | host | (port) | resource |
http:// | www.example.com | (:80) | /folder/file.html |
로컬 파일 시스템의 경우
예: file:///C:/경로/js/module.js
protocol | host | (port) | resource |
file | null | null | C:/경로/js/module.js |
로컬 파일 시스템에서 file:// 프로토콜을 사용할 때는 프로토콜이 file로 고정되고,
호스트와 포트가 없기 때문에 출처가 null로 간주된다.
! 여기서 드는 의문 !
근데 여기서 사용한 html 파일과 html에서 불러온 JavaScript 파일은 둘다 파일 시스템에서 로드된 동일 출처 인데, 왜 CORS 오류 나는 거임?
HTML과 JavaScript 파일 로드 차이점
- HTML 파일 로드:
- 브라우저는 로컬 파일 시스템(file:// 프로토콜)에서 HTML 파일을 열 수 있습니다.
- HTML 파일은 다른 리소스(이미지, CSS, JavaScript 등)를 포함할 수 있습니다.
- JavaScript 파일 로드:
- HTML 파일이 <script> 태그를 통해 JavaScript 파일을 로드하려고 할 때, type="module"이 없는 경우에는 일반 스크립트로 처리됨
- 일반 스크립트는 로컬 파일 시스템에서 문제없이 직접 로드할 수 있으며, 상대적으로 덜 엄격한 보안 정책이 적용
- type="module" 속성이 있는 경우에는 ES6 모듈로 처리되어 CORS 정책이 적용됨.
- 모듈 스크립트는 CORS 정책을 따르기 때문에 file:// 프로토콜을 사용할 때 문제가 발생
- 브라우저는 보안상의 이유로 로컬 파일 시스템에서 직접 모듈 스크립트를 로드하는 것을 차단함
- 이로 인해 CORS 오류가 발생하며, null 출처에서 다른 리소스를 로드할 수 없슴
- HTML 파일이 <script> 태그를 통해 JavaScript 파일을 로드하려고 할 때, type="module"이 없는 경우에는 일반 스크립트로 처리됨
즉,
<script src="./js/main.js"></script>
이렇게 쓰면 문제가 안됨
<script type="module" src="./js/main.js"></script>
type="module" 쓰는 경우 CORS 정책 적용
왜 같은 JavaScript인데 type="module" 속성이 있는 경우에만 CORS 정책이 적용되는가?
- 모듈 스크립트는 ES6 모듈의 특성상, 다른 모듈을 가져오기 위해 네트워크 요청을 사용한다. 이를 통해 브라우저는 더 엄격한 보안 정책을 적용하여, 동일 출처 정책(Same-Origin Policy, SOP)을 강제함.
type="module" 쓰고 싶은데 해결 방법은?
로컬 서버 사용하면 됨 ㅇㅇ
그러면 로컬 파일 시스템 대신 로컬 서버를 사용하여 파일을 제공함
쉽게 말해 로컬 서버에서 올려 `프로토콜, 호스트, 포트`를 같게 만들어 CORS 에러를 해결함.
어떻게?!
http-server , live-server 등 여러가지 로컬 서버들 중에 골라서 사용하면 됨!
npm install -g http-server
or
npm install -g live-server
터미널 창에서 위와 같은 명령어를 통해 전역으로 설치
http-server
or
live-server
이후에는 해당 명령어만으로 로컬 서버를 실행할 수 있음. 기본적으로 8080 포트에서 실행
요약
- 문제: type="module"을 사용한 스크립트가 로컬 파일 시스템에서 열릴 때 CORS 오류 발생.
- 이유: 브라우저 보안 정책인 동일 출처 정책(SOP) 때문.
- 해결책: 로컬 서버를 사용하여 파일을 제공. Node.js의 http-server를 사용하여 간단히 로컬 서버를 설정할 수 있다.
'Vanilla JS' 카테고리의 다른 글
[Vanilla JS] Intersection Observer API (0) | 2024.07.26 |
---|