일반적으로
<script>
태그는 html의<head>
태그 안에 작성한다.
<script>
를<head>
에 작성하면 css 등 외부로부터 불러오는 리소스 파일을 한 군데에서 관리할 수 있는 장점이 있다.
<!doctype html>
<html>
<title>title</title>
<link href="stylesheet.css" rel="stylesheet" type="text/css">
<script scr="script.js"></script>
<body>
...
</body>
</html>
하지만 이 방식은 브라우저가 HTML을 렌더링하는 것에 영향을 준다.
브라우저는 HTML마크업을 파싱하여 DOM트리를 구성하고 페이지를 렌더링한다.HTML을 파싱하는 동안 브라우저는
<script>
를 만날 때마다 파싱을 중지하고, script를 로드하고 실행하게 된다.이 과정에서 외부 스크립트를 로드하는 네트워크 왕복 시간과 자바스크립트를 실행하는 시간만큼 렌더링이 지연된다.
<!doctype html>
<html>
<title>title</title>
<style>
/* css */
</style>
<script type="text/javascript">
/* inline js */
</script> <body>
...
</body>
</html>
위와 같이 작성하면, 외부 스크립트를 로드하는 요청이 없어져서 빠르게 렌더링을 할 수 있따.
하지만 스크립트를 실행하는 동안<body>
의 내용은 사용자에게 보이지 않는다.
스크립트의 내용이 길어질수록 렌더링은 점점 늦어지게 된다.
<!doctype html>
<html>
<title>title</title>
<link href="stylesheet.css" rel="stylesheet" type="text/css">
<body>
...
<script scr="script.js"></script>
</body>
</html>
따라서 script가 렌더링을 막는 것을 방지하기 위해서 최근 웹에서는 일반적으로 위와 같이 script를
<body>
의 맨 아래에 삽입한다이와 같이 작성하면 body의 내용이 렌더링 된 이후에 script를 만나 로드하고 실행하기 때문이 위의 코드보다 렌더링의 타이밍이 더 빨라지게 된다.
script가 DOM을 조작하는 내용을 보함하고 있다면, script가 렌더링된 DOM에 접근할 수 있음으로 아래에 작성하는 것이 좋다.
script
는 다운로드와 실행이 순차적으로 진행되는 것과 달리 defer속성을 가진 script는 브라우저가<script defer>
를 만났을 때 다운로드를 시작하지만, html 파싱을 막지 않고</html>
을 만났을 때 실행된다.
async속성을 가진 script는
<script>
,<script defer>
와 마찬가지로 브라우저가 해당 요소를 만났을 때 외부 스크립트 다운로드를 시작한다.
defer와 마찬가지로 다운로드 중에 HTML 파싱을 막지 않았지만, 다운로드가 완료되면 즉시 실행하고 실행하는 동안 브라우저는 HTML 파싱을 멈춘다.
- 첫 번째 경우
: script 다운로드가 시작되자 마자 HTML 파싱이 script 실행이 완료될 때까지 멈춘다
- 두 번째 경우 (async)
: script 다운로드가 완료되면 HTML 파싱을 즉시 멈추고 script 실행이 완료되고 나서야 HTML 파싱이 재개된다.
- 세 번째 경우 (defer)
: HTML 파싱 도중에도 script 다운로드는 비동기적으로 일어나며, HTML 파싱이 멈춘 이후에서야 script 실행이 시작된다.