프로그래밍 언어/JavaScript

[JavaScript] html 문서에 JavaScript를 포함할때 어떻게 포함하는게 효율적일까? (head,body,defer, async)

반응형

blocked -> fetching.js -> executing.js -> parsing.html

head

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="main.js">    </script>
</head>
<body>

</body>
</html>

blocked -> fetching.js -> executing.js -> parsing.html

 

1.parsing html

사용자가 html 파일을 다운로드하였을 때 브라우저가 1줄씩 parsing 하게 된다.

이때 css와 병합해서 dom요소로 변환하게 된다.

 

2.blocked

html을 쭉 parsing 하다가 script 태그가 보이면 main.js를 다운로드해야 되네?라고 이해하고 html parsing을 멈추게 된다. 

 

3.fetching.js

script 태그에 해당되는 main.js 파일을 서버에서 다운로드 받게 된다.

 

4.executing.js

다운로드가 완료되면 main.js파일을 실행한다.

 

5.parsing html

그 후 나머지 html을 parsing하게 된다.

 

특징

js파일의 사이즈가 커지면 사용자가 웹사이트를 보는데 까지 많은 시간이 소요가 되는 단점이 있다.

body 제일 끝부분에 script 작성

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    
</head>
<body>

<script src="main.js">    </script>
</body>
</html>

1.parsing html

2.fetching js, executing js

페이지가 준비가 된 다음 script 태그를 만나서 script를 서버에서 받아오고, 실행하게 된다.

 

특징

페이지가 사용자들에게 main.js를 받기전에 이미 준비가 되어서 사용자가 html 콘텐츠를 볼 수 있는 장점이 있지만

사용자가 정상적인 페이지를 보기 전까지는 서버에서 main.js를 받아오는 시간도 기다려야되고 실행하는 시간도 기다려야 되는 큰 단점이 있다.

head + async

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script async src="main.js">    </script>
</head>
<body>


</body>
</html>

head안에 script를 이용하되, async라는 속성값을 사용하는 방법이다.

async는 boolean 타입의 속성값이기 때문에 선언하는 것만으로도 true로 설정이 되어서 async옵션을 사용할 수 있다.

 

브라우저가 html를 다운받아서 parsing을 하다가 async를 만나게 되면 병렬로 main.js파일을 다운로드가 시작된다.

이때 쭉 parsing을 하다가 main.js가 다운로드가 완료되면 parsing을 멈추고 다운로드된 main.js을 실행하게 된다. 실행을 다 하고 나서 나머지 html을 parsing 하게 된다.

 

특징

body끝에 사용한느 것보다는 fetching.js이 parsing 하는 동안 병렬적으로 일어나기 때문에 다운로드하는 시간을 절약할 수 있다. 하지만 main.js가 html이 parsing 되기도 전에 실행이 되기 때문에 만약 main.js파일에서 query select를 이용해서 dom요소를 조작한다 그러면 조작하려고 하는 시점에 html이 우리가 원하는 요소가 아직 정의되어 있지 않을 수 있다. 

또 하나는 html이 parsing하는 동안 언제든지 main.js를 실행하기 위해서 멈출 수 있기 때문에 사용자가 페이지를 보는데 시간이 여전히 조금 더 걸릴 수 있는 단점이 있다.

head + async(다수의 Script)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script async src="a.js">    </script>
    <script async src="b.js">    </script>
    <script async src="c.js">    </script>
</head>
<body>
</body>
</html>

먼저 다운로드 되는 js파일을 실행하게 된다.

즉, b가 먼저 다운로드 되면 b.js를 먼저 실행한다.

 

정의된 스크립트 순서에 상관없이 먼저 다운로드된 js파일을 실행한다.

만약 js파일이 순서에 의존적이라면?

즉, b라는 js파일이 실행되기전에 a라는 js파일이 먼저 선행되어야 한다면 async옵션을 사용하면 문제가 될 수 있다.

head + defer

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script defer src="main.js">    </script>
</head>
<body>
</body>
</html>

parsing을 하다가 defer를 만나게 되면 main.js를 다운로드 받자고 명령만 시켜놓고 나머지 html을 끝까지 parsing 하게 된다. 그리고 마지막에 parsing이 끝난 후 다운로드가 된 main.js를 실행하게 된다.

 

html를 parsing 하는 동안 필요한 main.js를 전부 다운로드 받아 놓고 html의 parsing을 먼저 해서 사용자에게 페이지를 보여준 다음 바로 이어서 main.js를 실행한다.

head + defer(다수의 Script)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script defer src="a.js">    </script>
    <script defer src="b.js">    </script>
    <script defer src="c.js">    </script>
</head>
<body>
</body>
</html>

parsing 하는 동안 필요한 js파일이 다운로드 받아지면서 parsing이 끝난 후 js파일을 정의한 순서대로 실행한다.

정의한 순서가 지켜지면서 우리가 원하는 a.js -> b.js -> c.js가 실행이 될걸 예상할 수 있다.

 

head + defer가 효율적이고 안전하다.

반응형