Javascript "async" 와 "defer"의 차이점
자바스크립트 파일을 작성하다보면 스크립트 파일을
<head> 에 위치할 때도 있고, <body> 태그의 맨 아래에 위치할 때도 있다.
자세하게 다뤄보지 않아서 막연하게 이유가 있겠거니 생각하다가
오늘 자세하게 어떤 순서로 흘러가는지 흐름을 알아보기로 했다.
우선은 <head> 안에 스크립트가 위치하는 경우이다.
이런 경우는 HTML 파일이 한 줄씩 HTML 파일을 읽다가
스크립트 파일을 만나면서 HTML 파일을 파싱하는걸 잠시 멈추고
필요한 자바스크립트 파일을 서버에서 다운(fetching)받고, 이것을 실행(executing)한 다음에
다시 HTML 파싱하는 부분으로 넘어간다.
이렇게하면 자바스크립트의 파일이 엄청 크고 다운받을게 많다면
사용자가 HTML 파일을 읽어볼 수 있을때까지의 시간이 많이 소요된다.
그래서 스크립트 파일을 헤드에 포함하는건 좋지 않은 방법이다.
다음 방법은 <body> 태그 가장 아래에 스크립트가 위치하는 경우이다.
이 경우는 HTML 파일을 쭉 파싱해서 페이지가 준비된 다음에
스크립트를 만나서 서버에서 받아오고 실행하게 된다.
그래서 스크립트가 준비되기 전에 사용자가 페이지를 받아 볼 수 있다.
하지만 이 방법도 단점이 존재한다.
이 페이지가 스크립트에 상당히 의존적인 페이지라면
사용자가 의미있는 컨텐츠를 보기 위해서는 스크립트의 파일을 받아오고 실행될 때까지
기다려야한다는 큰 단점이 존재한다.
그 다음은 <head> 안에 async를 이용한 스크립트이다.
async 라는 속성 값은 Boolean 타입으로 선언만으로 true 상태이다.
HTML 파일이 위에서부터 파싱을 하다가
async를 만나 병렬로 스크립트 파일을 다운 받기 시작한다
그리고 다시 파싱을 하다, 스크립트 파일의 다운이 완료되면
그때 파싱을 멈추고 다운로드 된 스크립트 파일을 실행한다.
실행을 다하고 난 뒤 나머지 HTML 파일을 다시 파싱한다.
이렇게하면 페칭이 파싱과 함께 병렬적으로 일어나며
스크립트 파일을 다운받는 시간을 절약할 수 있다.
하지만 자바스크립트가 HTML이 전부 파싱되기 전에 실행되기 때문에
만약 자바스크립트 파일을 조작할때 아직 HTML 파일이 정의 되어있지 않을 수 있다.
또한, 스크립트를 다운받다가 언제든지 스크립트 실행을 위해 파싱이 멈출 수 있기 때문에
사용자가 페이지를 보는데 여전히 시간이 걸린다.
그 다음은 <head> 안에 defer를 이용한 스크립트이다.
이 방법은 HTML 파일을 파싱하다가
스크립트 defer 를 만나면 스크립트 파일을 병렬로 다운만 받자 명령하고
나머지 HTML 파일을 끝까지 파싱한다.
그리고 마지막에 HTML 파일 파싱이 끝난 후
자바스크립트 파일을 실행하게 된다.
위의 흐름도만 봐도 defer이 좋은 옵션이라는걸 알 수 있다.
HTML 파일을 파싱한 후, 병렬형태로 다운받은 스크립트 파일을
HTML 파싱이 끝나자마자 스크립트를 실행해서 사용자에게 제공한다.
조금만 더 async 와 defer의 차이점을 알아보자면,
위 사진은 다수의 async 스크립트 파일들이다.
이렇게되면 HTML 파일을 파싱 중에
다수의 스크립트 파일을 만나 모두 다운받기 시작한다.
그래서 b.js 가 먼저 다운받아지면 b.js 를 먼저 실행하고,
a.js 가 다운되면 a.js 를 실행하고,
그 다음에 c.js를 실행하는 순서로 이루어진다.
즉, 지정된 순서와는 상관없이 먼저 다운받아지는 스크립트 파일을
먼저 실행하게 된다.
만약 나의 작업의 스크립트 실행 순서에 의존적인거라면,
async 옵션의 사용은 문제가 될 수 있다.
반대로 다수의 defer 같은 경우에는
HTML을 파싱하는동안 필요한 자바스크립트 파일들을 병렬 형태로 같이 다운을 받고,
HMTL 파일 파싱이 완료되면
그 다음에 준비 된 스크립트 파일을 순서대로 실행한다.
이 방식은 우리가 원하는 스크립트 실행 순서를 따르게 된다.
이렇게 여러개를 살펴보았을때
<head> 태그안에 defer 옵션을 사용해 스크립트 파일을 다운받고 불러오는게
제일 안전하고 확실한 방법이란걸 알 수 있었다.