![article thumbnail image](https://blog.kakaocdn.net/dn/GUEe3/btqNVAAnGA5/LBBo5MDVmknqPaRaoJecQ0/img.png)
아래와 같이 코드를 작성하면 모듈을 html 파일에 적용할 수 있습니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>모듈 적용</title>
</head>
<body>
<h1>테스트</h1>
<script type="module" src="./js/app.js"></script>
</body>
</html>
여기서 주의할 점은 반드시 script 태그에 type 속성값을 module로 설정해주어야 한다는 것입니다.
만약에 type 속성을 명시하지 않는다면
Uncaught SyntaxError: Cannot use import statement outside a module
이런 내용이 담긴 에러 메세지가 발생합니다.
또한, 만약에 위와 같은 코드가 담긴 파일을 로컬에서 직접 실행해보면 다음과 같은 에러 메세지가 발생합니다.
이를 해결하기 위해서는
먼저 터미널을 연다. http-server가 없다면
npm install http-server -g
위 키워드로 http-server를 전역으로 설치해 준 다음
npx http-server
위 명령어로 http-server를 실행시켜 해당 폴더를 서버에 올립니다.
http://127.0.0.1:8080
위 URL로 접속해서 에러가 사라진 것을 확인합니다.
그렇다면 이 에러 메세지가 발생한 원인은 무엇일까?
구글을 통해 검색하다 보니, SOP가 바로 그 원인이었습니다.
SOP (Same Origin Policy - 동일 출처 정책)
SOP는 '동일 출처 정책' 입니다. 어떤 출처(origin)에서 불러온 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한하는 브라우저의 보안 방식입니다.
이때 다른 출처와 같은 출처를 구분하는 기준은 URL의 프로토콜, 호스트, 포트가 같은가? 입니다.
example) https://news.naver.com/main/main.nhn?mode=LSD&mid=shm&sid1=101
- 프로토콜 => https://
- 호스트 => news.naver.com
- 포트 => (:80)
- 리소스 => /main/main.nhn?mode=LSD&mid=shm&sid1=101
위에서 포트까지의 부분이 같다면 같은 출처, 다르면 다른 출처로 간주됩니다. 그러나 이러한 정책이 모든 방식의 요청에 적용되는 것은 아닙니다.
예를 들어,
- <img> 태그로 다른 도메인의 이미지 파일을 가져오거나
- <link> 태그로 다른 도메인의 CSS를 가져오거나
- <script> 태그로 다른 도메인의 javascript를 가져오는 것
- 그 외에도 <video> <audio> <object> <embed> <applet> 태그
에는 동일 출처 정책이 적용되지 않습니다.
동일 출처 정책은 script에서 XMLHttpRequest 나 Fecth API를 사용해 다른 출처에 리소스를 요청할 때 적용됩니다.
결국 CORS 에러로 불리는 에러가 발생하는 이유는 이 동일 출처 정책이 적용되는 방식으로 다른 출처의 자원에 접근하려 했기 때문입니다.
그런데 우리가 위에서 작성했던 html 파일에서는 script에서 XMLHttpRequest 나 Fetch API를 사용해 무언가를 요청한 것도 아니고 동일 경로 내 하위 폴더의 script 파일을 요청했는데 왜 동일 출처 정책이 적용되지 않는 것일까?
이유는 바로, 모듈 스크립트의 특성 때문이다.
MDN의 javascript modules의 내용을 살펴보면 type을 module로 설정한 <script> 태그가 포함된 HTML 파일을 로컬에서 로드할 경우 자바스크립트 모듈 보안 요구사항 으로 인해 CORS 오류가 발생한다고 합니다. 그 때문에 XMLHttpRequest 나 Fetch API를 사용해 무언가를 요청한 것이 아님에도 불구하고 CORS 오류가 발생했었던 것입니다.
에러 메세지를 자세히 살펴보면, 출처가 null 로 넘어온 script에 대한 접근이 CORS 정책에 따라 제한되었다고 나와 있습니다. 에러 메세지에서 from origin 'null' 이라는 어구를 볼 수 있는데 이를 보니 로컬의 리소스를 요청할 대의 origin은 null로 설정되어 있다는 것을 알 수 있었습니다.
즉, c:/경로/index.html에서 ajax로 c:/경로/js/app.js에 리소스를 요청한 건 동일 경로의 리소스를 요청한 것이 아니고 c:/경로/index.html에서 null/js/app.js로 리소스를 요청한 것이 되어 CORS에러가 발생한 것입니다.
그렇기 때문에 서버에 올려 프로토콜, 호스트, 포트를 같게 만들면 CORS 에러가 해결될 수 있었던 것입니다.
정리하자면,
- <script type="module"></script> 는 로컬에서 실행 시 자바스크립트 모듈 보안 요구로 인해 CORS 에러가 발생합니다.
- 로컬에서 로컬 파일 리소스를 요청할 때는 origin(출처)가 null로 넘어가므로 CORS 에러가 발생합니다.
- http-server를 설치하여 해당 파일들을 서버에 올려 실행시키면 CORS 에러를 해결할 수 있습니다.
'시행착오' 카테고리의 다른 글
[MySQL] Alter Table 실행 도중 발생한 Connection Lost 에러 해결 (0) | 2022.08.23 |
---|---|
왜 forEach 메소드는 children 속성에 대해 동작하지 않을까? (0) | 2020.11.21 |