defer, async
defer
defer 속성은 <script> 태그의 속성중 한개로 페이지가 모두 로드된 후에 해당 외부 스크립트를 실행하기 위해 사용한다.
defer 속성은 명시하지 않으면 false 값을 가지게 되고, 명시하면 true 값을 가지게 된다.
보통 HTML 파일에는 <script> 태그의 src 요소를 통해 자바스크립트 위치를 지정해서 외부 스크립트를 불러올 수 있다.
<!doctype html>
<html>
<head>
<title>title</title>
<link href="stylesheet.css" rel="stylesheet" type="text/css">
<script src="script.js"></script>
</head>
<body>
HTML 태그들...
</body>
</html>
위와 같은 방법으로 <head></head> 태그 안에 작성하여 js, css 등 외부로부터 불러오는 리소스 파일들을
한 곳에서 관리할 수 있는 장점이 있다. 하지만 위 방식은 브라우저가 html 렌더링을 할 때 영향을 줍니다.
브라우저는 렌더링 엔진을 통해 HTML 태그를 파싱하여 DOM 트리를 구성하고 렌더링하여 사용자에게 보여준다.
HTML 태그를 파싱하는 동안 브라우저는 <script> 태그를 만날 때마다 파싱을 중지하고 스크립트를 로드하고 실행하게 됩니다. 이러한 과정에서 외부 스크립트를 로드하는 네트워크 왕복 시간, 자바스크립트 실행 시간만큼 렌더링이 지연된다.
그래서 이러한 렌더링 지연을 막기 위해서 또 하나의 방법은 HTML 태그 맨 밑쪽에 <script> 태그를 삽입하는 방법이다.
- HTML 태그 맨 밑으로 이동한 <script> 태그
<!doctype html>
<html>
<head>
<title>title</title>
<link href="stylesheet.css" rel="stylesheet" type="text/css">
</head>
<body>
HTML 태그들...
<script src="script.js"></script>
</body>
</html>
위 방법처럼 하게되면 HTML 태그들을 모두 파싱하여 DOM 트리로 구성한 후 <script> 태그가 로드된다.
이러한 방법으로 렌더링 지연을 방지할 수 있다.
또 하나의 방법은 위에서 설명했듯이 <script> 태그의 defer 속성을 사용하는거다.
- defer 속성 사용
<!doctype html>
<html>
<head>
<title>title</title>
<link href="stylesheet.css" rel="stylesheet" type="text/css">
<script defer src="script.js"></script>
</head>
<body>
HTML 태그들...
</body>
</html>
위 방법은 HTML 태그를 파싱하기전 script 태그의 속성인 defer 확인하고 자바스크립트 파일을 다운로드 하자고
명령만 시켜놓고 HTML 태그를 파싱하게 됩니다. HTML 태그 파싱이 모두 끝나면 미리 받아놓은 자바스크립트
파일을 로드하게 된다.
파싱하는 동안 필요한 자바스크립트 파일을 받아놓고 HTML 파싱이 완료 후 사용자에게 페이지를 보여준 다음
자바스크립트 파일을 실행하기 때문에 HTML의 파싱 DOM 트리에 접근할 수 있다.
async
<script> 태그의 속성 중 async 속성은 HTML 페이지와 완전히 독립적으로 동작한다.
async 속성이 있는 <script> 태그는 defer와 마찬가지로 백그라운드에서 다운로드 된다.
HTML 페이지는 파싱하는 동안 async 속성 스크립트가 다운이 완료될 때까지 기다리지 않고 파싱을 진행한다.
다운로드가 완료됐을 때 파싱을 잠시 멈추고 다운로드한 자바스크립트를 실행하게 된다.
즉, async 속성 스크립트는 비동기적으로 다운로드를 받고 다운이 완료되면 HTML 파싱을 멈추고
다운로드된 스크립트를 로드한다.
자바스크립트가 HTML 파싱이 완료되기 전에 실행되기 때문에 조작하려는 HTML DOM이 그려지지 않았을 경우
필요한 조작을 할 수가 없는 위험이 있다.