Frontend

defer, async 스크립트 더 들여다보기

mechaniccoder 2024. 3. 25. 00:43

브라우저에서 HTML parsing 하는 도중에 script(synchronous script)를 만나면 parsing을 멈추고 script 처리하는 것을 기다리게 됩니다. DOM은 초기 페이지 렌더링에 필수적인 리소스(critical resource)이므로 parsing이 완료될 때까지 페이지는 렌더링 되지 않습니다. 유저는 늦게 페이지 콘텐츠를 확인하게 되겠죠. 

HTML parsing blocking

async, defer script를 활용하면 이 문제를 해결할 수 있다는 것을 잘 아실 겁니다. 그런데 defer script를 실행하기 위해 CSSOM이 생성될 때까지 기다리며 DOMContentLoaded 이벤트를 지연시키고 script 순서에 영향받는 것을 알고 계셨나요?

이번 포스팅에선 async, defer script에 대해 좀 더 깊이 알아보는 시간을 갖고자 합니다.

 

defer

HTML parsing하는 도중에 백그라운드에서 script를 다운로드하고 DOM이 생성된 후에 script가 실행됩니다.

defer script timeline

이 과정에서 DOMContentLoaded 이벤트는 어디서 호출이 되는 걸까요? 스크립트가 실행되기 전일까요?

defer DOMContentLoaded

위 질문에 답하기 위해 2가지를 더 알아야 합니다.

 

1. DOMContentLoaded 이벤트는 defer script 실행이 완료될 때까지 발생하지 않습니다.

2. defer script는 CSS가 다운로드되고 CSSOM 트리가 생성될 때까지 실행 되지 않습니다.

 

위 두 내용을 종합해보면 결국 CSSOM 트리가 생성되고 script가 실행될때까지 DOMContentLoaded 이벤트는 발생하지 않게 됩니다. CSS 파일이 너무 커서 다운로드에 오래 걸리면 defer script 실행이 지연되고 DOMContentLoaded 이벤트에도 영향을 주게 되는 것이죠.

defer의 특징 한 가지를 더 알아보죠. defer는 script 태그 순서에 영향을 받습니다. HTML에 다음과 같은 순서로 정의돼 있고 small.js의 다운로드가 먼저 완료됐다고 하겠습니다. 그러나 defer script는 script 순서별로 실행되기 때문에 아무리 small.js가 먼저 다운로드됐더라도 big.js가 다운로드 되고 실행될 때까지 지연됩니다.

    <script src="big.js" defer></script> // small.js보다 먼저 실행됨
    <script src="small.js" defer></script>

 

async

defer와 마찬가지로 HTML parsing과 동시에 백그라운드에서 다운로드받지만 실행 시점에 차이가 있습니다.

1. HTML parsing 도중에 다운로드가 완료된 경우 HTML parsing을 blocking 하게 됩니다.

async timeline1

2. HTML parsing이 완료되고 나서 다운로드가 완료된 경우 HTML parsing을 blocking 하지 않습니다.

async timeline2

그럼 DOMContentLoaded 이벤트는 어디서 발생할까요? defer와는 달리 async는 DOMContentLoaded 이벤트에 영향을 주지 않습니다. 따라서 둘은 관련이 없는 것으로 이해하면 됩니다. (실행 이전 또는 이후에 발생 가능)

또한 async는 CSS의 다운로드와 parsing과는 별개로 처리됩니다. 앞서 defer의 경우, CSS가 다운로드 되고 parsing되는 것을 기다렸죠.

 

요약

  • defer는 CSS download, parsing을 기다리며, DOMContentLoaded 이벤트를 지연시킨다.
  • defer는 script 순서별로 실행된다. 다운로드가 빨리 되더라도 순서가 늦으면 실행되지 않는다.
  • async는 다운로드 시점에 따라 HTML parsing을 blocking할 수도 있다.
  • async는 DOMContentLoaded, CSS download와 parsing과 관련이 없이 별개로 동작한다.

 

마치며

defer, async는 잘 알고 있다고 생각했는데 자세히 들여다보니 모르는 것 투성이였습니다. 이번 기회를 통해 브라우저 동작을 더 깊이 알 수 있어 좋은 시간이었던 것 같네요. 내가 알고 있는 것을 진짜로 알고 있는지 항상 생각하고 정리하는 자세를 가져야겠습니다.

 

References