Frontend

Defer vs Async

Reife 2023. 3. 17. 16:01

HTML에서 외부 스크립트를 로드하는 데 사용하는 defer 속성과 async 속성에 대해 알아보겠습니다.

두 속성은 외부 스크립트의 로드와 실행 방식을 결정합니다.

아래 코드 블럭에서 볼 수 있듯이 HTML 파일의 head 태그 안에 있는 script 태그의 속성으로 defer 또는 async를 부여할 수 있습니다. 해당 태그는 Boolean 타입인데, 디폴트가 True여서 defer 또는 async 라고 명시하기만 하면 속성이 적용됩니다.

 

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="main.js"></script>
  <script src="a.js" defer></script>
  <script src="b.js" async></script>
</head>
<body> </body>
</html>

 

 

async

 

 

async 속성이 적용된 스크립트는 HTML 구문 분석과 동시에 로드됩니다. 로드되는 동안에는 파싱이 그대로 진행되지만 다 받아지면 파싱을 중단하고 스크립트를 실행합니다.

 

스크립트가 여러개인 경우

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

 

위와 같이 스크립트 여러개를 모두 async 속성으로 불러올 경우에는 js 실행 순서가 보장이 되지 않습니다. 스크립트 파일의 크기에 따라서 불러오는 속도가 서로 다를 수 있는데, 이때 async 속성을 가진 스크립트는 로드가 끝나는 즉시 js를 실행합니다.

 

 

 

defer

 

 

async와 동일하게 파싱과 동시에 스크립트를 받아옵니다. 하지만 구문 분석이 완전히 끝난 후에야 JS 파일이 실행된다는 차이가 있습니다. 또한 async 속성은 파싱이 끝난 후 DOMContenetLoaded라는 이벤트가 발생하지 못하도록 막고, JS 파일이 실행된 후에 해당 이벤트가 발생하도록 합니다.

 

스크립트가 여러개인 경우

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

 

defer 속성은 async 속성과 달리 HTML 상에 스크립트가 작성된 순서에 따른 실행을 보장합니다. 파일 크기에 따라 불러오는 시점에는 순서가 없지만, HTML 파싱이 끝난 후에는 HTML에 작성된 대로 순차적으로 JS 파일을 실행합니다. 

 

 

 

 

 

async 속성과 defer 속성 모두 파싱을 중단시키지 않고 JS를 받아온다는 점에서 중요합니다. 파싱이 늦춰지면 그만큼 사용자가 UI를 볼 수 있는 시간이 늦춰지고, 이는 사용성에 큰 악영향을 끼치기 때문입니다.

 

그러나 async 속성은 스크립트가 다 불러와지면 바로 실행하기 때문에 여전히 파싱을 중단할 수 있다는 문제를 지니고 있습니다. 또한 스크립트가 서로 종속적이어서 순서가 중요하다면 async 속성처럼 순서를 고려하지 않고 실행하는 방식은 적합하지 않습니다.

 

반면 defer 속성은 스크립트를 병렬적으로 불러오고, 파싱 이후에 스크립트를 실행하므로 async 보다 사용성 측면에서 더 바람직합니다. 또한, HTML에 명시된 순서대로 스크립를 실행하므로 개발자가 의도한 순서대로 실행이 가능하다는 장점도 있습니다. 따라서, 스크립트를 비동기적으로 불러와야 하는 경우가 발생하면, async 속성보다는 defer 속성을 사용하시는 것을 권장합니다.

 

 References

https://youtu.be/tJieVCgGzhs
https://developer.mozilla.org/ko/docs/Web/HTML/Element/script