Script 태그의 위치
- head 태그 내부
- body 태그 마지막
- async / defer
대부분의 코드를 작성할 때 body 태그의 마지막에 script 태그를 사용했지만 그 이유는 정확히 알지 못했다. script 태그가 body 태그의 최하단에 위치해야 하는 이유는 무엇일까?
이에 대해 알아보려면 먼저 브라우저 작동원리에 대해 알아야 한다.
위의 브라우저 동작원리에서 1~2가 중요하다.
HTML을 읽어 내려가는 과정에서 script 요소를 만나면 파싱을 중단하고 중단한 상태에서 자바스크립트 코드(파일)을 로드 후 자바스크립트 코드를 파싱한다. 그 후 다시 HTML 파싱이 계속된다.
즉 HTML을 읽는 과정에서 자바스크립트 로드와 파싱을 위해서 중단되는 시점이 생기고, 그에 따라 Display에 표시되는 것이 지연된다.
또 다른 이유로는 HTML 파싱이 끝나고 DOM 트리가 생기기 전에 자바스크립트가 실행되어 DOM 조작을 할 경우 에러가 발생할 수 있다는 점이다.
정리해보자면,
script 태그가 body 태그의 최하단에 위치해야 하는 이유
async, defer
body 태그 최하단에 위치하지 않고도 위의 2가지 이유를 방지하기 위해 사용하는 script 태그의 async / defer 속성을 알아보자.
<script async src="index.js"></script>
<script defer src="index.js"></script>
async 또는 defer 속성을 사용하면 공통적으로 HTML 파싱과 동시에 스크립트 로드가 이루어진다.
이후,
추가적으로 async의 경우 비동기적으로 여러 스크립트를 로드, 실행하기 때문에 스크립트의 순서에 상관없이 실행될 수 있다. 따라서 실행 순서가 서로 영향이 있는 스크립트들을 사용할 때에는 주의해서 사용해야 한다. (동기적인 실행을 위해서는 async=false로 설정하여 순서대로 실행할 수 있다.)
defer는 순서대로 실행된다.
script 태그가 body 태그의 최하단에 위치한다면 async와 defer가 필요없겠지만 그렇지 않을 경우 async와 defer를 활용해서 볼 수 있는 효과와 주의해야할 점은 아래와 같다.
효과)
async, defer 모두 HTML 파싱과 스크립트 로드가 동시에 진행되므로 HTML 파싱이 완료되는 시간을 줄일 수 있다.
주의할 점)
async는 HTML 파싱과 동시에 스크립트 로드를 하지만 스크립트 실행은 HTML 파싱이 중지된 상태에서 진행되기 때문에 중간에 HTML 파싱이 멈추는 시점이 생길 수 있다. 다만 실행 순서를 감안해야 한다.
defer는 HTML 파싱과 동시에 스크립트를 로드하고 HTML 파싱이 완료된 후 스크립트가 실행된다. 이는 위에서 설명한 'script 태그가 body 태그의 최하단에 위치해야하는 이유'를 모두 보충해준다.
📌참고자료
브라우저 작동원리 https://wormwlrm.github.io/2021/03/27/How-browsers-work.html#tldr
script 태그위치 https://junhobaik.github.io/js-script-position/