스크립트 로드
html은 위에서 부터 코드를 하나씩 불러 브라우저에 표시해 사용자에게 보여주고 이러한 특성 때문에
일반적으로 html 파일에서 script를 불러오는 <script>
태그는 때는 html의 제일 마지막에 위치한다
html 마크업을 표시하다가 script를 만난 시점에 script를 다 불러오기 전 까지 html을 읽는 것을 잠시 중단하기 때문
<body>
<div>...</div> // 1번
<script src="..."></script>
<div>...</div> // 2번
</body>
불러올 html이 이런 식의 구조를 가지고 있다면 1번을 불러온 뒤 스크립트를 불러오는 동안 2번의 마크업은 읽는 것이 중단되고
스크립트를 다 불러오기 전 까지는 사용자는 반쪽짜리 화면만 볼 수 밖에 없고 사용자는 페이지가 멈춘 것 처럼 느낄 수도 있게된다
그래서 보통은 다음과 같이 코드를 작성한다
<body>
<div>...</div>
<div>...</div>
<script src="..."></script>
<script src="..."></script>
<script src="..."></script>
<script src="..."></script>
</body>
이렇게 해도 문제는 생길 수 있다
html 자체의 크기가 너무 크고 거기에 script 마저 크다면 html을 한 세월 걸려서 다 받고... script도 한 세월 걸리게 되는데
이 경우에는
- 페이지 자체가 사용자에게 완전한 서비스를 제공하는데 까지 시간이 너무 오래걸린다
- html을 다 받아 사용자에게 온전한 화면은 보여주지만 script를 불러오는 동안에는 페이지가 불완전하게 작동한다
defer script
위 문제를 해결할 수 있는 문법이 중 하나는 defer
다
이 속성이 있는 스크립트는 브라우저가 즉시 불러오지 않고 백그라운드에서 불러온다
즉, html을 읽다 defer script를 만나면 html은 그대로 불러오면서 뒤에서 스크립트 또한 동시에 불러오는 것
그리고 스크립트를 다 불러오는 것을 완료했다고 해서 즉시 실행되지 않고 페이지가 완벽하게 불러와질 때 까지 실행이 지연된다
<body>
<div>...</div> // 1번
<script defer src="..."></script>
<div>...</div> // 2번
</body>
1번이 불러와진 후 2번과 defer script가 동시에 불러와진다
다음을 보자
<body>
<div>...</div> // 1
<script>
document.addEventListener('DOMContentLoaded', () => alert('DOMContentLoaded')); // 2
</script>
<script defer src="./test.js"></script> // 3
<div>...</div> // 4
</body>
// in test.js
alert('defer');
페이지 구성이 끝날 때 까지 실행이 지연되는 defer script와 DOM 로드가 끝나고 나서 실행되는 이벤트인 DOMContentLoaded 가 같이 있다면 순서는 어떻게 될까?
1 - 4 - 3 - 2 다
defer가 먼저 실행되고 나서 DOMContentLoaded가 실행된다
defer script끼리의 순서
스크립트의 용량이 100인 big.js와 1인 small.js가 다음 처럼 불러와지고 있다
...
<script defer src="./big.js"></script>
<script defer src="./small.js"></script>
...
우선 브라우저는 스크립트들을 전부 살펴본 후에 병렬적으로 다운로드한다
big과 small의 다운로드가 병렬로 시작되는데 당연하게도 small의 다운로드가 먼저 끝난다
하지만 스크립트를 문서에 추가한 순서대로 실행되게끔 설계되어있기 때문에 big이 실행될 때까지 기다린 후 small이 실행된다
defer script는 항상 html이 완전히 로드된 후에 실행된다는 것을 유의해야한다
이는 사용자는 여전히 html이 완전히 로드될 때 까지 defer script를 사용하지 못한다는 것을 의미하는데
사용자를 위해 적절한 로딩 표시나 해당 스크립트의 기능 사용이 불가능함을 표시해주어야한다
async script
async script도 defer와 비슷하게 코드를 만났을 때 백그라운드에서 로딩하지만 페이지와 독립적으로 동작한다
- async script는 페이지의 로드가 끝나는 것을 기다리지않고 스크립트 로드가 완료되면 바로 실행한다 (이 때 스크립트 실행중에는 html 로드가 멈추게 된다)
- DOMContentLoaded와 같이 있을 때 서로를 기다리지 않는다
- 스크립트 순서에 상관없이 먼저 다운로드된 스크립트가 먼저 실행된다 (이를 'load-first’ order라고 부른다)
동적 스크립트
자바스크립트를 이용해서 동적으로 스크립트를 추가해 줄 수 있다
let script = document.createElement('script');
script.src = "/path";
document.$someElem.append(script);
이 코드에서 document.$someElem.append(script);
가 실행될 때 path에 있는 스크립트의 다운로드가 시작되는데 이 때 스크립트는 동적 스크립트(async script)로 행동한다
그렇기 때문에 위에서 나열한 async script와 동일한 특성을 갖는다
이 특성은 script.async=false
옵션으로 끌 수 있다
async script는 페이지와 완전히 독립적으로, 순서가 없이 실행되기 때문에 방문자 수를 나타내거나, 광고와 관련된 스크립트 등 페이지를 이용하는데 전혀 문제가 없는 기능들이어야 한다
'JavaScript' 카테고리의 다른 글
Object.defineProperty (0) | 2021.09.06 |
---|---|
클래스, 믹스인 (Mixin) (0) | 2021.07.13 |
주요 노드 프로퍼티 (0) | 2021.07.09 |
DOM 수정 (0) | 2021.07.08 |
modal에 keydown 이벤트 추가하기 (tabindex) (0) | 2021.06.02 |