script 태그에서 Async와 Defer의 차이

담당
황찬우
완료
완료
유형
HTML CSS
비고

요약


asyncdefer는 스크립트 태그를 사용하여 웹 페이지에 스크립트를 추가할 때 사용하는 어트리뷰트로, 스크립트의 로드 및 실행 시점을 제어합니다.
 

async 어트리뷰트:

  • 스크립트는 비동기적으로 로드됩니다.
  • 스크립트의 로드와 실행은 다른 자원들과 동시에 진행됩니다.
  • 스크립트의 실행 순서는 로드가 완료된 순서에 따라 달라집니다. 순서가 보장되지 않습니다.
  • 사용 예: 독립적인 스크립트에 사용하거나 실행 순서가 중요하지 않은 경우에 유용합니다.

defer 어트리뷰트:

  • 스크립트도 비동기적으로 로드되지만, HTML 파싱과 스크립트 실행의 순서가 보장됩니다.
  • 스크립트의 실행은 HTML 파싱이 완료된 직후, 즉 DOM 생성이 완료된 직후에 진행됩니다.
  • 스크립트의 실행 순서는 스크립트가 문서에 추가된 순서대로 보장됩니다.
  • 사용 예: DOM 전체가 필요한 스크립트에 사용하거나 실행 순서가 중요한 경우에 유용합니다.
 
따라서, async는 로드 속도를 최적화하며 순서가 중요하지 않은 경우에 사용하고, defer는 스크립트 실행 순서를 보장하며 DOM이 필요한 스크립트에 사용하는 것이 일반적인 관례입니다.
 

async / defer


모던 웹브라우저에서 돌아가는 스크립트들은 대부분 HTML보다 ‘무겁습니다’. 용량이 커서 다운로드받는 데 오랜 시간이 걸리고 처리하는 것 역시 마찬가지이죠.
브라우저는 HTML을 읽다가 <script>...</script> 태그를 만나면 스크립트를 먼저 실행해야 하므로 DOM 생성을 멈춥니다. 이는 src 속성이 있는 외부 스크립트 <script src="..."></script>를 만났을 때도 마찬가지입니다. 외부에서 스크립트를 다운받고 실행한 후에야 남은 페이지를 처리할 수 있습니다.
이런 브라우저의 동작 방식은 두 가지 중요한 이슈를 만듭니다.
  1. 스크립트에서는 스크립트 아래에 있는 DOM 요소에 접근할 수 없습니다. 따라서 DOM 요소에 핸들러를 추가하는 것과 같은 여러 행위가 불가능해집니다.
  1. 페이지 위쪽에 용량이 큰 스크립트가 있는 경우 스크립트가 페이지를 ‘막아버립니다’. 페이지에 접속하는 사용자들은 스크립트를 다운받고 실행할 때까지 스크립트 아래쪽 페이지를 볼 수 없게 됩니다.
이런 문제를 해결할 수 있는 <script> 속성이 있습니다. 바로 defer와 async입니다.
 

defer


defer 어트리뷰트는 HTML 문서 내의 스크립트 태그에 적용되며, 웹 페이지를 더 효율적으로 로드하고 스크립트 실행을 최적화하기 위한 목적으로 사용됩니다.
 
  1. 비동기적 로드와 HTML 파싱
      • defer 어트리뷰트가 있는 스크립트는 HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행됩니다.
      • 이것은 웹 페이지의 로딩 시간을 단축하고 사용자 경험을 향상시키는 데 도움을 줍니다.
  1. 자바스크립트 파싱과 실행 시점
      • defer 스크립트의 파싱과 실행은 HTML 파싱이 완료된 직후, 즉 DOM 생성이 완료된 직후 진행됩니다.
      • 이는 DOM 요소들이 준비되어 있어서 자바스크립트가 정확하게 작동하도록 보장합니다.
  1. 백그라운드 다운로드
      • 브라우저는 defer 속성이 있는 스크립트(즉, 지연 스크립트)를 '백그라운드'에서 다운로드합니다. 이것은 다운로드 중에도 HTML 파싱이 멈추지 않음을 의미합니다.
      • 이로써 웹 페이지의 로딩 속도가 빨라지고 사용자는 더 빠르게 페이지를 볼 수 있습니다.
  1. 스크립트 실행의 지연
      • defer 스크립트는 페이지 구성이 끝날 때까지 실행을 지연시킵니다. 즉, HTML 문서가 완전히 로드되고 DOM 요소들이 생성된 후에 실행됩니다.
      • 이것은 스크립트가 페이지 로딩을 방해하지 않으면서도 웹 페이지의 상호작용 및 동작을 개선하기 위한 유용한 기능입니다.
 
따라서 defer 어트리뷰트를 사용하면 웹 페이지의 성능을 향상시키고 사용자 경험을 최적화할 수 있습니다. 이것은 특히 큰 웹 페이지나 많은 자바스크립트 코드를 가진 웹 애플리케이션에서 유용합니다.
 
사용법
<script defer src="long.js"></script> <script defer src="small.js"></script>
브라우저는 성능을 위해 페이지에 어떤 스크립트들이 있는지 쭉 살펴본 후에야 스크립트를 병렬적으로 다운로드합니다. 그런데 이 때 크기가 작은 small.js이 long.js보다 먼저 다운로드 될 수 있습니다. 하지만 명세서에서 스크립트를 문서에 추가한 순서대로 실행하라고 정의했기 때문에 small.js는 long.js 다음에 실행됩니다.
 
* script src가 없는 경우(외부 스크립트가 아닌 경우)에는 defer 속성이 무시됩니다.
 

async


async 어트리뷰트는 자바스크립트 파일의 비동기적 로드와 실행을 관리하기 위한 HTML 스크립트 태그 속성입니다.
 
  1. 비동기적 로드
      • async 어트리뷰트가 있는 스크립트는 HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행됩니다.
      • 이것은 브라우저가 다운로드 중인 스크립트 파일을 기다리지 않고 다른 자원들을 로드하거나 파싱하는 동안 비동기적으로 스크립트 파일을 다운로드합니다.
  1. 실행 시점
      • async 스크립트의 파싱과 실행은 자바스크립트 파일의 로드가 완료된 직후 진행됩니다.
      • 이로써 HTML 파싱은 중단되지 않지만, 자바스크립트 파일의 로드와 실행이 비동기적으로 이루어집니다.
  1. 순서 보장이 없음
      • async 어트리뷰트를 지정한 여러 개의 스크립트 태그가 있다면, 스크립트 태그의 순서와는 상관없이 로드가 완료된 자바스크립트 파일부터 먼저 실행됩니다.
      • 따라서 스크립트 실행 순서가 보장되지 않습니다. 이는 각 스크립트 파일이 독립적으로 동작해도 문제가 없을 때 사용됩니다.
  1. 순서가 중요한 경우에는 주의
      • 웹 페이지에서 스크립트 실행 순서가 중요한 경우에는 async 어트리뷰트를 사용하면 안됩니다.
      • 대신 defer 어트리뷰트를 사용하여 순서를 보장하면서도 비동기적으로 스크립트를 로드할 수 있습니다.
 
async 어트리뷰트를 사용하면 스크립트 파일을 비동기적으로 로드하고 실행할 수 있지만, 순서가 중요한 경우에는 주의해야 합니다. 순서를 보장하려면 defer 어트리뷰트를 사용하거나 스크립트를 적절히 조절하여 문제를 해결할 수 있습니다.
 
 
사용법
<script defer src="long.js"></script> <script defer src="small.js"></script>
비동기 스크립트는 서로를 기다리지 않습니다. 위치상으론 small.js가 아래이긴 하지만 long.js보다 먼저 다운로드되었기 때문에 먼저 실행됩니다. 이렇게 먼저 로드가 된 스크립트가 먼저 실행되는 것을 'load-first order’라고 부릅니다.
 

async vs defer


async
defer
순서
load-first order/순서보장X. 문서 내 순서와 상관없이 먼저 다운로드된 스크립트가 먼저 실행됩니다.
문서에 추가된 순서
용도
방문자 수 카운터나 광고 관련 스크립트같이 독립적인 스크립트에 혹은 실행 순서가 중요하지 않은 경우
DOM 전체가 필요한 스크립트나 실행 순서가 중요한 경우
 

참고한 사이트


모자딥다 [38장 브라주어즤 렌더링 과정] / https://comhwang.tistory.com/45