JavaScript & Node.js
#.1 Async vs Defer
Haksae
2022. 1. 5. 23:37
HTML에서 JS를 포함할 때 어떻게 포함하는게 효율적인가?
1. head 안에 스크립트를 포함
- 브라우저가 한줄씩 파싱하다가 CSS와 병합하면서 DOM 요소로 병합 (parsing HTML)
- 파싱하다가, 필요한 자바 스크립트 파일을 다운받아서 실행 (fetching js, executting js)
- 단점 : js 파일이 엄청 크면, 출력까지 오래 걸릴 수 있음
- 이러한 방식으로 보통 하지 않음
2. body 안에 스크립트를 포함 (주로 뒤에)
- JS를 받기 전에도 페이지가 준비가 되어서, 사용자가 먼저 페이지에 컨텐츠를 볼 수 있음
- 단점 : 웹사이트가 자바스크립트에 의존적이라면 사용자가 의미있는 컨텐츠를 보기 위해서는 오래 기다려야하는 단점이 있다.
3. head+async
- async는 boolean 타입의 속성 값, 선언하는 것만으로도 true로 설정됨
- async를 사용하게되면, 브라우저가 HTML을 다운로드 받아서, 파싱을 하다가 async 파일을 병렬로 다운로드 받자고 명령해놓고
- 다시 파싱을 하다가, fetching js가 끝나면 그 때 파싱을 멈추고 다운로드된 JS 파일을 실행
- 실행을 다 하고나서 나머지 HTML을 파싱
- 다운로드하는 시간을 절약할 수 있다는 장점이 있음
- 단점 : 다양한 스크립트를 실행하게되면, 스크립트가 순서 의존적이라면 문제 발생 가능
- HTML이 파싱 전에 실행되기 때문에, 만약 JS파일이 조작하려는 시점에 HTML 파일이 아직 정리되어있지 않을 수 있다 / HTML을 파싱하다가 자바스크립트 실행을 위해 멈춰야하는 단점이 있다.
4. head + defer
- HTML 파싱하다가 defer를 보면 JS를 다운만 받아놓고, 끝까지 파싱. 그리고 파싱이 끝나고 마지막에 전체가 실행됨
- defer가 가장 효율적이고 안전함
* 파싱의 중단
- 일반 스크립트(classic script)와 달리 async와 defer 속성이 있는 스크립트의 다운로드(패치)는 HTML 파싱을 중단시키지 않습니다.
모든 스크립트의 실행은 HTML 파싱을 중단시킵니다. (defer는 파싱 후에 실행되도록 강제되어 중단시킬 수가 없을 뿐입니다.)
*렌더링 블록킹
- async나 defer 모두 렌더링 차단에 대한 어떠한 것도 보장하지 않습니다. 이것은 사용자와 스크립트에 달려 있습니다. (예를 들어, 스크립트가 onLoad 이후에 실행되도록 하는 것).
* 실행 순서의 보장
- async 속성이 추가된 스크립트는 패치되는 순서에 따라 임의로 실행되는데 반하여 defer 속성과 일반 스크립트(classic script)는 페이지에 명시된 순서대로 실행이 됩니다.
결론
일반적으로, 외부 스크립트를 로딩할 경우, 스크립트가 렌더링을 위해서 무언가 하지 않는 이상 항상 async 또는 defer를 선택해 사용해야 합니다.
- async는 스크립트를 로딩 중간에라도 일찍 실행하는 것이 중요한 경우 사용합니다.
- 좀 더 중요도가 떨어지는 스크립트는 defer를 사용합니다.