script 요소의 async, defer 어트리뷰트
Goal
<script>
요소의 async
, defer
어트리뷰트에 대해 알아보기
JavaScript 파일의 실행 순서
브라우저의 파싱 작업은 동기적 방식이라고 할 수 있다.
브라우저의 렌더링 과정에서 HTML이 파싱될 때 <script>
요소를 만나면 HTML 파싱 작업은 즉시 중지되고 자바스크립트 파일이 실행되기 때문이다.
전통적으로 <script>
요소는 <head>
요소 안에 쓰는 것이 일반적이었지만, 자바스크립트 파일을 전부 <head>
요소에 넣어버리면 자바스크립트 코드를 전부 내려받고, 파싱하고, 해석이 끝날 때까지 페이지 렌더링이 멈추게 된다. <script>
요소의 이러한 특성은 HTML 페이지를 렌더링하는 속도에 상당한 영향을 미칠 수 있다. 또한 사용자에게는 화면이 멈춘 것처럼 느껴지게 되는 문제가 생길 수 있다.
그리고 <head>
요소에 스크립트가 있을 때 자바스크립트 코드 내에 DOM을 조작하는 부분이 있다면 오류가 발생할 수 있다. DOM이 아직 생성되지 않았을 수 있기 때문이다.
따라서 이러한 문제점을 방지하기 위해 <body>
요소 가장 아래에 자바스크립트를 위치시키면 DOM이 완성되지 않은 상태에서 자바스크립트가 DOM API를 사용하는 것과 자바스크립트 로드, 파싱, 실행으로 인해 HTML 요소가 렌더링이 지연되는 일을 방지할 수 있는 장점이 있다.
<body>
요소 가장 아래에 자바스크립트를 위치시키는 방법 외에 자바스크립트 파싱에 의해 DOM 생성이 지연되는 문제를 해결하기 위해 HTML5부터 <script>
태그에 async
와 defer
어트리뷰트가 추가되었다. 이 속성들을 추가하면 HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 실행된다.
defer 어트리뷰트
- 브라우저는
defer
속성이 있는 스크립트를 '백그라운드'에서 다운로드 한다. - 그래서
defer
스크립트를 다운로드 하는 중에도 HTML 파싱이 중단되지 않는다. defer
스크립트는 자바스크립트 파싱과 실행이 HTML 파싱이 완료된 직후 진행된다.defer
속성이 있는 스크립트가 여러 개인 경우 문서에 추가된 순으로 실행된다.- DOM 생성 완료 직후 스크립트가 실행되지만
DOMContentLoaded
이벤트 발생 전에 실행된다.DOMContentLoaded
이벤트는defer
속성이 적용된 스크립트의 실행을 기다리기 때문이다.
async 어트리뷰트
async
속성이 있는 스크립트도defer
스크립트와 마찬가지로 '백그라운드'에서 다운로드된다.async
는 자바스크립트 파싱과 실행이 자바스크립트 파일의 로드가 완료된 직후 진행된다. 스크립트 실행 중에는 HTML 파싱이 멈춘다.async
를 사용하면 파일들이 병렬적으로 로드되며 다운로드가 끝난 순서대로 해석된다.async
와defer
가 둘 다 사용된 경우async
가 우선하게 된다.DOMContentLoaded
이벤트와async
스크립트는 서로 기다리지 않는다.DOMContentLoaded
이벤트는async
스크립트 실행 전에 발생될 수도 있고, 실행 후에 발생될 수도 있다.
같이 보기
reference
- 한선용 역, 니콜라스 자카스 저, 《프론트엔드 개발자를 위한 자바스크립트 프로그래밍》, 인사이트, 2013년
- 안재우 역, 코디 린들리 저, 《DOM을 깨우치다》, O'Reilly, 2013년
- 이웅모 저, 《모던 자바스크립트 Deep Dive》, 위키북스, 2020년
- JAVASCRIPT.INFO - defer, async 스크립트