[WEB] 스크립트를 비동기로 불러오는 두 가지 방법 - async / defer

<script src="foo.js"></script>
<script src="bar.js" async></script>
<script src="baz.js" defer></script>

요즘 프론트엔드 환경에서는 하나의 entry point만 두고
나머지 모듈은 전부 import/export한 다음 번들링하는 것이 익숙해진지 오래다.

심지어 entry point 파일 하나 조차도 create-react-app 같은 툴들이 대신 생성해주거나
초기 세팅 때만 심어두면 더이상 건드릴 일이 잘 없기 때문에
<script>를 어느 위치에 넣어야하는지에 대한 고민을 할 일이 거의 없는 듯 하다.

요즘의 스크립트 태그란 '구글 애널리틱스나 애드센스 넣을 때나 복붙하면 되는 것' 정도로만 인식하던 차에 async, defer 키워드를 보게 되었다.

async는 그냥 비동기로 불러오는 속성이 생겼구나.. 정도로 생각하겠지만, defer도 비동기 어쩌구라길래 정확한 차이점이 궁금해져 조사해보았다.

1. default - 동기식으로 로드

특별하게 설명할 것 없는 '클래식' 그 자체다.
HTML을 파싱하다가 <script src="...">를 만나면 JS를 다운로드하고, 실행하고, 마저 파싱하러 간다.

HTML 파싱이 중간에 (특히, 네트워크 통신 시간 동안) 중단되는 것이 사용자들에게는 사이트 렌더링이 뚝뚝 끊기는 듯한 체감을 줄 수 있기 때문에, 비동기 속성을 사용하지 않는 한 특별한 경우가 아니라면 <body> 마지막에 스크립트 태그를 넣도록 하자.

2. async - 비동기 다운로드 + 바로 실행

다운로드는 비동기로, 실행은 바로하는데 실행할 때는 앞의 경우와 마찬가지로 HTML 파싱이 블락된다. 그리고 스크립트 실행 순서가 보장되지 않는다.

이 특성 때문에, 스크립트의 작업이 무겁지 않고 다른 스크립트와 독립적인 경우에 사용하면 이점을 누릴 수 있을 것이다. 하지만 DOM을 조작하는 코드가 있다면 실행 시점에 DOM 트리가 제대로 구성되지 않을 수 있으므로 사용하지 않는 것이 좋아보인다.

3. defer - 비동기 다운로드 + HTML 파싱 후 실행

다운로드는 비동기로 하되, DOM 파싱이 끝날 때까지 실행을 지연시킨다.
<script> 순서가 보장되고 DOM 파싱이 끝나고 DOMContentLoaded 이벤트 이전에 실행된다.

다운로드 시에는 비동기의 이점을 누리면서, 동기적으로 실행을 처리할 수 있다는 것이 장점으로 보인다.

참고 자료

좋은 웹페이지 즐겨찾기