내가 한 노력들

[ Javascript ] script문의 위치에 대한 고민 ( defer와 async의 차이) 본문

IT 공부/Javascript

[ Javascript ] script문의 위치에 대한 고민 ( defer와 async의 차이)

JONGI-N CHOI 2022. 1. 15. 21:26

js코드를 파일로 만들어서 html에 가져오는 경우에, script 선언 위치를 어디에 할지에 대한 고민이있습니다. 

대부분은 body가 끝나는 부분에 선언하는 경우가 많습니다. 

 

그 이유는 ?? 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="array.js"></script>
</head>
<body>
</body>
</html>

위의 코드처럼 javascript 코드를 head 부분에 선언한 경우에 어떻게 실행되는지를 설명해보면, 

브라우저는 해당 html코드를 한줄한줄 해석하게 됩니다. 

그러다가 script 태그를 만나, 해당 array.js라는 js파일을 다운받는 과정이 필요하고 실제로 코드에 적용하기 위해서 js파일을 실행하는 시간이 필요합니다. 

 

그러면, 브라우저는 js파일을 다운받고 실행하는 시간동안은 나머지 HTML 코드를 parsing을 하지 못하게 되고, 유저들은 그만큼 기다리는 시간이 길어지게 됩니다. 

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<script src="array.js"></script>
</body>
</html>

그렇기 때문에, body가 끝나는 부분에 js파일을 선언하는 경우가 많습니다. 

 

하지만, 위와같은 경우에도 단점이 있는데, 해당 HTML파일이 js파일에 크게 의존적인 경우에는 어떻게 될까요?? 

예를들어, API를 통해서 외부로부터 데이터를 받아와서 랜더링해줘야 한다던가, UI적인 동작이 포함되어있는 경우에 

js가 실행되기 전까지는 아무런 동작이되지 않습니다. 

 


위와같은 문제를 해결하기 위해서 생긴 것이 async와 defer 

async

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<script async src="array.js"></script>
</body>
</html>

async는 비동기를 의미합니다. 

js파일을 우선 비동기적으로 다운로드 받고, 실행시킵니다. 

 

그럼, js파일을 다운받고 실행하는 행위가 비동기적으로 일어나기 때문에 HTML 파싱이 끊키지않아 시간이 절약될 수 있습니다. 

 

하지만, 이 방법에도 단점이 존재하는데 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<script async src="a.js"></script>
<script async src="b.js"></script>
<script async src="c.js"></script>
</body>
</html>

위와 같이 a, b, c의 js파일이 존재하는데, 순서가 중요한 경우에 

비동기적으로 하게되면, 다운로드가 빨리 끝나는 js파일부터 실행이 됩니다. 

그러면 원하는 대로 동작을 하지 않게되겠죠.

 

defer

결론부터 말하면 아직까지는 defer가 가장 이상적으로 js파일을 동작시킬 수 있는 방법이라고 생각됩니다. 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<script defer src="array.js"></script>
</body>
</html>

defer는 async와 마찬가지로, 비동기적으로 js파일을 다운받습니다.

하지만 async와의 다른점은, 다운받고 바로 실행시키는 것이아닌, HTML파싱이 끝나면 실행시킵니다. 

 

async에 존재하던 단점은?? 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<script defer src="a.js"></script>
<script defer src="b.js"></script>
<script defer src="c.js"></script>
</body>
</html>

async에서 여러 js파일을 불러올때의 문제점은 순서가 보장되지 않는다는 점이었는데,

defer을 사용하면, 다운로드는 비동기식으로, 실행은 HTML파싱이 끝난뒤에 순서대로 실행되게 됩니다.

 

그러면, 비동기식으로 다운받기때문에 시간이 절약되고, 순서대로 실행되기 때문에 순서가 중요한 js파일을 불러올때도 문제없이 실행하는 것이 가능해집니다. 

 


user strict

추가적으로, js파일 위에 'use strict'을 선언해주는 것이 좋습니다. 

user strict

기존의 javascript는 워낙 자유도가 좋은 언어이기 때문에, 반대로 문제점도 많습니다. 

 

변수의 선언도 하지않고 초기화를 해준다던가, 개발하면서 여러가지 실수를 할 수 있는데, use strict를 사용하면 그러한 문제점들을 에러 발생으로 실행이되지 않도록 해줍니다. 

 

또한, 실행시간에 있어서도 이점이 있다고 합니다.