My Boundary As Much As I Experienced

script태그의 async/defer의 동작 방식 본문

FrontEnd/Javascript(Vanilla)

script태그의 async/defer의 동작 방식

Bumang 2024. 2. 29. 15:16

자바스크립트 파싱에 의한 DOM 생성이 중단되는 문제를 근본적으로 해결하기 위해 HTML5부터 script 태그에 async와 defer 어트리뷰트가 추가되었다.

async와 defer 어트리뷰트는 다음과 같이 src 어트리뷰트를 통해 외부 자바스크립트 파일을 로드하는 경우에만 사용할 수 있다. 즉, src 어트리뷰트가 없는 인라인 자바스크립트에는 사용할 수 없다.

<script async src="extern.js"></script>
<script defer src="extern.js"></script>

async와 defer 어트리뷰트를 사용하면 HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행된다. 하지만 자바스크립트의 실행 시점에 차이가 있다.

async 어트리뷰트

html파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행된다. 단, 자바스크립트의 파싱과 실행은 자바스크립트 파일의 로드가 완료된 직후 진행되며, 이때 HTMl 파싱이 중단된다.

여러 개의 script 태그에 async 어트리뷰트를 지정하면 script태그의 순서와는 상관없이 로드가 완료된 자바스크립트부터 먼저 실행되므로 순서가 보장되지 않는다. 따라서 순서 보장이 필요한 script 태그에는 async 어트리뷰트를 지정하지 않아야 한다.

defer 어트리뷰트

async 어트리뷰트와 마찬가지로 HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행된다. 단, 자바스크립트의 파싱과 실행은 HTML 파싱이 완료된 직후, 즉 DOM 생성이 완료된 직후)이때 DOMContentLoaded 이벤트가 발생한다) 진행된다. 따라서 DOM 생성이 완료된 이후 실행되어야 할 자바스크립트에 유용하다.

 

 

DOMContentLoaded 이벤트와 load와의 관계

load는 모든 리소스(CSS, images..)가 다운로드된 다음에 이벤트 호출된다.

렌더트리가 다 로드되고 발생한다.


DOMContentLoaded는 HTML document를 전부 읽고 DOM트리를 완성하는 즉시 이벤트가 호출된다.

즉, cssom이 로드되기 전에 발생한다. 

 

그래서 load의 경우 이미지 리소스가 다 불러와진 후에 이벤트가 실행되기 때문에 리소스가 많을 경우 속도 저하가 발생한다.
그러나 이미지와 관련된 이벤트가 실행에 있어 필수적인 경우에는 속도 저하와 상관없이 load를 사용해야 된다.

 

DOMContentLoaded 이벤트와 async 스크립트는 서로를 기다리지 않는다.

그러나 defer는 DOMContentLoaded가 끝나기 전에 js파일 로딩이 끝났다고 하더라도 DOMContentLoaded가 끝나길 기다렸다가 실행된다.