defer, async 스크립트
DOMContentLoaded, load, beforeunload, unload 이벤트
모던 JavaScript 튜토리얼을 학습하고 정리한 글입니다.
모던 웹브라우저에서 돌아가는 스크립트들은 대부분 HTML보다 '무겁고' 용량이 크기 때문에 다운로드 받는 데 시간이 오래 걸리고 처리하는 것도 마찬가지로 오래걸릴 수 있다.
브라우저는 HTML을 읽다가 <script>...</script>
태그를 만나면 스크립트를 먼저 실행해야 하기 때문에 DOM 생성을 멈추게 된다.
이는 src
속성이 있는 외부 스크립트 <script src="..."></script>
를 만났을 때도 마찬가지로 동작한다.
<p>... 스크립트 앞에 있는 컨텐츠</p>
<script src="https://..."></script>
<p>... 스크립트 뒤 컨텐츠</p>
위와같은 브라우저의 동작 방식은 두 가지 중요한 이슈를 만드는데
1. 스크립트에서는 스크립트 아래에 있는 DOM 요소에 접근할 수 없다. 따라서 DOM 요소에 핸들러를 추가하는 것과 같은 여러 행위가 불가능하다.
2. 페이지 위쪽에 용량이 큰 스크립트가 있는 경우 스크립트가 페이지를 '막아버립니다.' 페이지에 접속하는 사용자들은 스크립트를 다움받고 실행할 때 까지 스크립트 아래쪽 페이지를 볼 수 없게 된다.
이런 부작용들을 피할 수 있는 몇 가지 방법이 있다.
스크립트를 페이지 맨 아래 놓는 것이 하나의 방법이 될 수 있다. 이 방법을 사용하면 스크립트 위에 있는 요소에 접근할 수 있고, 페이지 컨텐츠 출력을 막지 않는다.
<body>
... 스크립트 위 컨텐츠들...
<script src="https://..."></script>
</body>
위에서 정리한 첫 번째 방법은 완벽한 해결책이 될 수 없다. HTML 문서가 아주 큰 경우를 가정했을 때 브라우저가 HTML 문서 전체를 다운로드한 뒤 스크립트를 다운받게하면 네트워크 속도(또는 모바일 네트워크 접속)가 열악한 곳의 경우 페이지가 느려질 수 있다.
이러한 문제를 해결할 수 있는 <script>
속성이 있는데 defer
와 async
이다.
브라우저는 defer
속성이 있는 스크립트를 '백그라운드'에서 다운로드 한다.
따라서 defer(지연) 스크립트를 다운로드하는 도중에도 HTML 파싱이 멈추지 않는다. 그리고 defer 스크립트 실행은 페이지 구성이 끝날 때 까지 지연된다.
<script>
에 src
가 없으면 defer
속성은 무시된다.)async
속성이 붙은 스크립트는 페이지와 완전히 독립적으로 동작한다.
async 스크립트는 defer 스크립트와 마찬가지로 백그라운드에서 다운로드 된다. 따라서 HTML 페이지는 async 스크립트 다운이 완료되길 기다리지 않고, 페이지 내 컨텐츠를 처리, 출력한다. (하지만 async 스크립트 실행중에는 HTML 파싱이 멈춘다. - 옮긴이)
async
스크립트가 여러 개 있는경우, 그 실행 순서가 제각각이 된다. (실행은 다운로드가 끝난 스크립트 순으로 진행된다.)async
와 defer
공통점async
와 defer
스크립트는 다운로드 시 페이지 렌더링을 막지 않는다는 공통점이 있다.
따라서, async
와 defer
를 적절히 사용하면 사용자가 오래 기다리지 않고 페이지 컨텐츠를 볼 수 있게 할 수 있다.
async
와 defer
차이점비교 | 순서 | DOMContentLoaded |
---|---|---|
async | load-first order. 문서 내 순서와 상관없이 먼저 다운로드 된 스크립트가 먼저 실행된다. | 비동기 스크립트는 HTML 문서가 완전히 다운로드 되지 않은 상태라도 로드 및 실행될 수 있다. 스크립트 크기가 작거나 캐싱 처리 되어있을 때 혹은 HTML 문서 길이가 아주 길 때 발생한다. |
defer | 문서에 추가된 순 | 지연 스크립트는 문서 다운로드와 파싱이 완료된 후에, DOMContentLoaded 이벤트 발생전에 실행된다. |