script 태그의 위치
렌더링 엔진은 script태그를 다운로드하거나 실행하는 중에는 파싱을 멈춘다.
자바스크립트 파일은 css나 html을 변경시킬 가능성이 있기 때문이다.
- head,body태그 최상단
파싱을 시작하자마자 script 태그를 다운로드한다.
파싱을 막기 때문에 script태그를 먼저 다운로드하고 실행 후 파싱한다.
실행 순서를 정할 수 있다.
다만 존재하지 않는 DOM요소에 접근시 에러가 발생할 수 있다.
- body태그 최하단
파싱이 끝난 뒤에 script 태그를 다운로드 시작한다.
js파일에 의존성이 높을경우 사용자경험이 좋지 못하다.
- defer
병렬로 백그라운드에서 다운로드한다.
다운로드 하는 중에도 HTML 파싱을 멈추지 않는다.defer
스크립트의 실행은 페이지 구성이 끝날 때까지 지연된다.
defer
스크립트는 DOM이 준비된 후에 실행되지만 DOMContentLoaded
전에 실행된다.
아래는 예시 코드이다.
1 | <p>...스크립트 앞 콘텐츠...</p> |
페이지의 콘텐츠가 모두 출력된다.
DOMContentLoaded
이벤트는defer
스크립트가 실행된 후에 발생하므로 alert창은 DOM트리가 완성되고defer
스크립트의 실행이 완료된 후에 실행된다.async
async
도 마찬가지로 백그라운드에서 다운로드 된다. 따라서 HTML 페이지는 async
스크립트 다운이 완료되길 기다리지 않고 페이지 내 컨텐츠를 출력한다.( 하지만 async
스크립트 실행중에는 HTML 파싱이 멈춘다.)
DOMContentLoaded
이벤트와 async
스크립트는 서로를 기다리지 않는다.
- DOM 트리를 다 만든 후에
async
스크립트 다운로드가 끝났을 경우DOMContentLoaded
이벤트는async
스크립트 실행 전에 발생할 수 있다. - 마찬가지로
async
스크립트가 DOM트리를 만들기 전에 다운로드 되었을 경우async
스크립트의 실행이 끝난 다음DOMContentLoaded
이벤트가 발생한다.
아래는 예제 코드이다.
1 | <p>...스크립트 앞 콘텐츠...</p> |
async
스크립트는 그 특징 떄문에 실행순서를 보장할 수 없다. 먼저 다운로드가 끝난 스크립트 순으로 실행된다. 즉 small.js가 long.js보다 먼저 실행된다.
또한 alert의 실행시점도 예측할 수 없다.
이러한 특징으로 인해 구글 어널리틱스같은 독립적인 역할을 하는 서드파티 스크립트를 삽입할 때에 유용하다. 개발중인 스크립트에 의존하지 않고 독립적으로 동작하기 때문이다.
1 | <script async src="https://google-analytics.com/analytics.js"></script> |