header안 script태그
header안에 script 태그를 포함하게 되면 사용자가 html파일을 다운받았을 때 브라우저가 위에서 한 줄씩 분석한다.(parsing) 분석하고 이해한 것을 css와 병합해서 DOM요소로 변화하게 된다.
html을 parsing하다가 script 태그를 만나게 되면 main.js를 다운받는 동작을 시행한다. 그래서 html parsing을 중단한 후 main.js파일을 서버에서 다운받아 실행한 다음 다시 html을 parsing한다.
만약 main.js 파일이 사이즈가 어마어마하게 크거나 인터넷이 느리면 main.js 파일을 다운받는데 오랜 시간이 대기해야 한다. 따라서 웹사이트를 보는데 까지 많은 시간이 걸리는 단점이 있다.
Body 끝 부분 script태그
브라우저가 html을 다운받아 parsing해서 페이지가 준비 된 다음에 script태그를 만나 서버에서 받아와 main.js를 실행한다. js를 받기 전에 페이지가 준비되어 사용자가 페이지 컨텐츠를 볼 수 있다.
사용자가 기본적인 html에 컨텐츠를 빨리 볼 수 있다는 장점이 있지만, 만약에 웹사이트가 자바스크립트에 의존적 즉, 사용자가 의미 있는 컨텐츠를 보기 위해서 js를 이용해서 서버에 있는 데이터를 받아 온다던지, DOM 요소를 더 예쁘게 꾸며든다든지, 그런 식으로 동작하는 웹페이지라면 사용자가 정상적인 페이지를 보기 전까지는 fetching(서버에서 js파일을 받아오는 동작), executing(실행 동작) 시간이 오래 소요되기 때문에 많은 시간을 기다려야 하는 단점이 있다.
head + async
async를 사용하게 되면 브라우저가 html 다운로드 받아서 parsing하다가 async를 발견해 병렬로 main.js파일을 다운받아야 하는 명령을 전달한다. 다시 parsing하다가 main.js가 다운로드 완료되면 그 때 parsing하는 것을 멈추고 다운로드 된 js파일을 실행한다. 실행을 다하고 난 후 남은 html을 parsing한다.
body끝에 사용하는 것보다 fetching이 parsing하는 동안 병렬적으로 일어나기 때문에 다운로드 받는 시간을 절약할 수 있다. 하지만 js가 html이 parsing되기도 전에 실행이 되기 때문에 만약 js파일에서 queryselector를 이용해서 DOM요소를 조작한다면 조작하려고 하는 시점에 html이 사용자가 원하는 요소가 아직 정의되어 있지 않을 수 있는 단점이 있다.
html을 parsing하는 동안에 언제든지 js를 실행하기 위해서 멈출 수 있기 때문에 사용자가 페이지를 보는데 시간이 오래 소요될 수 있는 단점이 있다.
head + defer
html을 parsing하다가 script 태크에 defer을 만나 main.js파일을 병렬로 다운 받기를 명령한다. 그리고 나머지 html을 끝까지 parsing하고 난 후 다운로드 되어진 js파일을 실행한다. defer이 가장 좋은 옵션이다.
html을 parsing하는 동안 필요한 js파일을 다 다운로드 받은 후 html parsing을 먼저해서 사용자에게 페이지를 먼저 보여준 다음에 js파일을 실행한다.
참고 : 드림코딩