07
23

HTML5 에서는, <script>태그에, defer또는 async속성을 부여하는 것으로, 이러한 read가 HTML 퍼스를 방해하지 않게 할 수가 있습니다. 이렇게 하면 사이트의 기본 콘텐츠를 로드하는 속도가 어느 정도 빨라집니다.

async어쨌든 defer, 그렇게 자세하게 동작을 설명한 기사를 찾을 수 없었기 때문에,이 기사에서는 이러한 동작에 대해 설명합니다.

 

이벤트 정보

 

우선, async과 defer의 행동을 이해하는 데 중요한 두 가지 이벤트를 이해합시다.
둘 다 MDN에 충분한 정보가 있으므로이 기사에서는 그렇게 자세히 설명하지 않습니다.

 

 

DOMContentLoaded

 

HTML 퍼스가 완료된 직후에 실행합니다.

MDN

 

 

Load

 

HTML의 퍼스가 완료해, CSS나 이미지등의 다운로드와 표시, JavaScript 파일의 다운로드와 실행 등, 모든 자원의 처리가 완료(이 타이밍을 Document Complete라고도 합니다) 직후에 실행합니다.

MDN

 

 

읽는 방법

 

어떤 시점에서 읽을 수 있는지에 대해 WHATWG 규격서 에는 매우 알기 쉬운 그림이 붙어 있습니다.

이것을 베이스로, 이벤트등을 추가해, 동작의 다이어그램을 작성했습니다.

 

 

1. 동기 읽기(기본값)

 

<script>태그 defer에도 async붙이지 않으면 HTML 퍼스중에 <script>태그에 도착하는 대로, 퍼스를 일시 정지해, JS 파일의 다운로드와 실행을 실시합니다.
JS 파일의 실행이 완료될 때까지 HTML 퍼스는 재개되지 않습니다.

구현 코드:

 

<script src="./script.js">

 

 

 

2.async

 

<script>태그에 async속성을 추가하여 비동기적으로 JS 파일을 다운로드하고 실행합니다.

다운로드는 HTML 퍼스를 멈추지 않고 병렬로 다운로드를 진행합니다.
다운로드가 완료되면 JS 파일이 실행되고 실행 중에 HTML 퍼스가 일시 중지됩니다.
다운로드는 HTML 퍼스 등을 실시하는 메인 thread와는 다른 thread로 실행되는 한편, JS 파일의 실행 자체는, 같은 메인 thread로 행해지기 때문에, HTML 퍼스와 동시 병행으로 실행되는 것은 아닌 것에 주의하십시오.

또, 복수의 <script>태그가 async첨부로 기술되고 있는 경우, 그러한 실행 순서는 <script>태그를 쓴 순서에는 실행되지 않는 것에도 주의가 필요합니다.

위의 그림에서는, 다운로드·실행 모두 퍼스전에 완료하고 있습니다만, 다운로드 완료(≒ 실행 개시)나 실행 완료가, DOMContentLoaded이벤트 실행 후가 되는 경우도 있습니다.
load이벤트보다는 전에 실행됩니다. JavaScript 파일의 실행 완료가 load이벤트 실행의 조건이기 때문입니다.

구현 코드:

 

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

 

 

 

3. defer

 

<script>태그에 defer속성을 추가하는 것으로, HTML 퍼스 완료 후, DOMContentLoaded이벤트의 직전에 (※ WHATWG 사양 ) JS 파일을 실행합니다.


실행은 퍼스 완료 후입니다만, 다운로드는 async마찬가지로 <script>태그가 퍼스 되는 대로 즉시 비동기적으로 (메인 thread와는 다른 thread로) 실행됩니다.

 

또, async와는 달리, 복수의 <script>태그가 defer첨부로 기술되고 있는 경우, <script>태그를 쓴 순서대로 실행되는 것도 특징입니다.

예를 들어,

 

<script src="/a.js" defer></script>
<script src="/b.js" defer></script>
<script src="/c.js" defer></script>
<script defer src="/a.js"></script>
<script defer src="/b.js"></script>
<script defer src="/c.js"></script>

 

이와 같은 설명의 경우, a.js 의 처리가 완료하고 나서 b.js 가 실행되어, b.js 의 처리가 실행되고 나서 c.js 의 처리가 실행됩니다.

구현 코드:

 

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

 

 

 

어느 것이 빠른가

 

앞의 그림에서는 HTML 퍼스 처리에 걸리는 시간이 흩어져 있었으므로, 통일해 본 그래프도 작성해 보았습니다. 우선, async 나 defer 에 비해, 디폴트 (어느 속성도 붙지 않는 경우)는 느립니다. 이는 JS 다운로드로 HTML 퍼스가 중지되기 때문입니다.

 

async 와 defer 를 비교하면 어느 쪽이 빠르다고 단언하기는 어렵습니다만, 지금까지 나는 defer좋지 않을까 생각합니다.

앞에서 언급했듯이 async의 경우 다운로드가 완료된 직후 JS가 실행됩니다. 따라서, async 의 경우 JS 가 실행되는 타이밍은, load 이벤트의 전이라고 하는 것 이외, 언제 실행되는지 모릅니다.

 

HTML 퍼스가 완료되기 전에 다운로드가 완료하면, JS 의 실행으로 HTML 퍼스가 블록 될 가능성이 있습니다. 이 경우 HTML 퍼스 완료가 느려집니다.


다운로드 완료가 HTML 퍼스 완료 후의 경우, 당연히 HTML 퍼스는 블록 되지 않습니다. 그림에서는, JS 의 실행 완료까지의 시간이 defer 보다 느립니다만, 통상은 렌더링이나, 화상등 다른 리소스 읽어들여등의 처리도 행해지고 있기 때문에, load까지의 시간을 늦추는 것은 별로 없을까 생각 합니다.

 

다운로드 완료가 HTML 퍼스 완료 후의 경우에서도, defer에 비해 큰 퍼포먼스상의 메리트는 없을 것 같기 때문에, 확실히 실행을 늦출 수가 있는 defer가 좋을 것이 아닌가, 라고 하는 것이, 지금의 내 결론입니다.

COMMENT
 

인기 글


최근 글