HTML에서 JS 파일을 로드시에 기본으로 로드하는 방식 , async를 사용하는 방식 , defer을 사용하는 방식 총 3가지가 있다.
기본으로 로드하는 방식
자바스크립트는 기본적으로 parser blocking resource(파서 차단 리소스)이다.
async , defer 모두 사용하지 않고 기본 모드로 브라우저는 문서(HTML)를 파싱해서 읽다가 스크립트를 만나면 진행하던 파싱을 멈추고 스크립트를 다운 -> 파싱 -> 실행 후 다시 문서를 파싱한다.
스크립트가 인라인으로 선언된 경우 -> 스크립트를 파싱하고 실행하지만
외부에서 선언된 경우 ->외부 스크립트를 다운로드하고 파싱하고 실행한다.
스크립트를 만나면 다운로드 -> 파싱 -> 실행할때 까지 문서 파싱이 중단됨으로 화면 랜더링에 시간이 더 소요된다.
async
문서를 파싱하는 동안 스크립트를 만나면
1.문서 파싱과 함께 스크립트를 다운받고
2.다운로드가 끝나고 스크립트를 실행하는 동안 문서(HTML)파싱을 중단하 고
3.스크립트 실행이 끝난 후 남은 문서를 읽는다.
예를 들어서
<script src="async3.js" async> // 3초
<script src="async2.js" async> // 2초
<script src="async1.js" async> // 1초
async스크립트로 선언한 실행이 다음과 같이 실행된다면
async1 > async2 > async3 순서로 스크립트가 실행될 것이다.
왜? 앞에서 설명한 대로 스크립트를 다운받고 다운이 끝난 순서대로 문서 를 읽기 때문에
주의할점
중간에 스크립트가 먼저 실행될경우 아직 HTML에서 참조하지 않은 id,class를 사용해버리면 스크립트가 오류가 날것이다.
->이유 : 당연하게도 async로 선언해버리면 스크립트를 실행하는동안 html파싱을 중단하기 때문에 아직 파싱되지 않은 HTML 태그를 참조할 수 없을 것이다.
<script defer>
브라우저가 스크립트 태그를 만나면 문서 파싱을 계속하면서 스크립트 파일을 다운로드한다. 하지만 async와 다르게 문서 파싱을 멈추지 않고 끝까지 실행하며 태그를 만났을 때 실행한다. 즉 DOMcontentLoaded 발생 이전에 실행해야 함을 나타낸다.
defer를 사용하지 않으면 기본적으로 true이고 사용하게되면 false이다. 일반 스크립트를 body태그 맨 밑에 삽입하는 것과 비슷한 효과이다.
정리
async 와 defer 모두 script를 다운받는 동안 문서 파싱을 중단하지 않는다는 공통점이 있지만 async는 스크립트를 다운 완료가 되면 문서 파싱을 중단하고 스크립트를 실행하지만 defer는 문서 파싱이 다 끝난 후에 다운받은 스크립트를 실행한다.