보통 HTML파일과 자바스크립트 파일을 따로 만들고, HTML 파일보다 자바스크립트 파일의 용량이 더 무겁다. 자바스크립트 파일을 읽어오는 구문의 위치 혹은 방식에 따라 동작하는 성능이 달라질 수 있다.

 

 script 태그의 위치에 따른 비교

head 태그에 위치하는 경우

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>

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

 head 태그 안에 위치할 경우, js 파일이 엄청 크다면 js 파일을 읽는 데에만 많은 시간이 걸려 HTML을 불러오는 데에 시간이 오래 걸린다.

 

 여기서 Loading JS(혹은 Fetching JS)는 js파일을 서버로부터 받아온다는 것이고, Executing JS는 js 파일을 실행하는 시간이다.

 

body 태그의 맨 밑에 존재하는 경우

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
    <script src="main.js"></script>
</body>
</html>

 body 태그의 맨 밑에 js 파일을 읽어오는 구문이 존재할 경우이다. HTML을 빠르게 보여줄 순 있겠지만, js 파일 용량이 상당히 크고 js 파일에 따라 HTML의 각 요소들이 변하게 될 경우 정상적인 HTML을 사용자가 보는 데에 시간이 오래 걸리게 된다.

 

 async vs defer

head 태그 안에 있으면서 asyn라는 속성 값을 쓰는 경우

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

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

 앞선 경우와 달리 Parsing HTML과 Loading JS가 어느 정도 겹쳐서 일어나기 때문에 시간을 줄일 수 있다. 허나 Parsing HTML과 Loading JS가 겹치기 때문에, 만약 Parsing HTML이 덜 되었는데 js 파일에서 요구하는 HTML 요소가 없는 경우 오류가 생겨 조금 위험할 수 있다.

 

head 태그 안에 있으면서 defer라는 속성 값을 쓰는 경우

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

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

 loading 이후 parsing HTML을 멈추는 동시에 곧바로 executing JS를 하는 async 방식과는 달리, defer의 경우는 parsing HTML을 하다가 script 구문을 만나게 되면 단지 loading JS 명령만 하게 된다. 이후 parsing HTML이 끝나고나면 executing JS가 된다.

 

다수의 js 파일이 존재할 때 async와 defer의 차이

async

 만약 다수의 js 파일이 존재할 경우, async를 사용했다면 loading(fetching)과 executing이 연달아 일어나기 때문에 시간을 절약할 수는 있다. 허나 js 파일이 실행되는 순서가 중요하게 코드가 짜여 있다면 (예로 a -> b -> c로 js 파일이 execute되어야 웹페이지의 기능이 정상적으로 작동한다면) 오류를 범할 수도 있다.

 

defer

 defer의 경우는 parsing HTML을 하다가 script 구문을 만났을 때 병렬로 loading JS를 하게 되고, executing은 script 구문을 만난 순서에 따라 직렬로 진행된다. 따라서 순서가 중요하다면 defer를 썼을 때 async처럼 얽히지 않을 것이다.

 

 따라서 결론적으로는 defer를 사용하는 것이 속도 측면에서(head 안 혹은 body 맨 밑에 위치하는 것과 비교했을 때) 빠르고 오류도 범할 가능성이 낮기 때문에 가장 효율적이다.

 

use strict

 JavaScript는 초기에 아주 급하게 만들어졌고, 상당히 유연한 언어이기 때문에 때때로 개발자의 실수를 허용하기도 한다. 예를 들자면

a = 6;
console.log("hello world");

 위와 같이 코드를 작성해도 "hello world"를 출력한다. JavaScript에서 변수를 선언할 때는 var, let, const를 사용해야 하는데도 말이다. 허나 다음과 같이

"use strict";

a = 6;
console.log("hello world");

 "use strict"를 작성한다면 에러를 발생시킨다. JavaScript에서 기존에 조용히 무시되는 에러들을 출력하기 때문이다. 그래서 다음과 같이

"use strict";

const a = 6;
console.log("hello world");

 "use strict"에서 코드가 작성된다면 에러를 무시할 수 없도록 올바르게 코드를 작성해야 하고 a 변수에는 var이나 let, const가 들어가야 에러를 출력하지 않고 "hello world"가 출력될 것이다.

 

 JavaScript 코드를 작성할 때 이처럼 strict mode를 사용해주는 것이 좋다. 기존에 용인되어 오던 작은 실수들을 에러로 출력하여 코드를 고칠 수 있도록 해주기 때문이다. 이는 좀 더 정확한 JavaScript 코드를 짤 수 있게 해준다. 그리고 작은 실수들은 자바스크립트 엔진이 최적으로 성능을 발휘하는 데에 악영향을 끼치기에 더더욱 strict mode를 사용해주는 것이 좋다.

 

 

 

이미지 출처 : https://betterprogramming.pub/improve-page-load-performance-with-these-different-script-loading-techniques-b0d912eae7b1

유튜브 드림코딩 채널 : https://www.youtube.com/watch?v=tJieVCgGzhs

 

+ Recent posts