async / defer : script 태그 작성 위치에 대하여

MihyunCho·2021년 3월 15일
0
post-thumbnail

html에서 script를 작성할 때 어느 위치에 작성하는게 좋을지 생각해본적이 있다.🤔
여러가지 방법이 있지만 가장 효율적인게 어떤 것인지, 최선은 무엇인지 따져보기 위해서 되짚어보는 async & defer

<!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="main.js"></script>
</head>
<body>
    
</body>
</html>

html을 한줄씩 파싱해서 css 분석한 것을 합쳐 DOM요소로 변환하는데, script 가 head안에 있을 때 위에서부터 아래로 하나씩 파싱하다가 script태그를 만나면 html 파싱을 멈추고 main.js를 서버에서 다운받는다.
이것을 실행 한 뒤 다시 html 파싱을 하는데 , 만약 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 src="main.js" ></script>
</body>
</html>

그래서 body 닫는태그 안에 script 를 넣는 경우가 있는데, 이렇게 하면 html을 쭉 파싱하다가 script를 만나면 서버에서 js 파일을 받아오고 실행하게 된다.
그래서 js를 받기 전 웹사이트 사용자들은 사이트를 보게되서 html을 빨리 보게 된다는 장점이 있다.
하지만 해당 사이트가 만약 js에 의존적, 즉 사용자가 의미있는 컨텐츠를 보기위해서는 js를 통해서 서버에 있는 데이터를 받아온다던지 DOM요소를 예쁘게 꾸며준다던지 그런 사이트라면, 사용자가 정상적인 사이트를 보기 전까지는 서버에서 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>
    <script async src="main.js" ></script>
</head>
<body>
    
</body>
</html>

head 안에 script를 두고 async 라는 속성을 쓴다.
boolean 타입의 속성이기 때문에 설정하는 것만으로 True인 상태가 된다.
이것을 사용하게 되면 브라우저가 위에서부터 차례대로 파싱하다가 script를 만나게 되면 병렬로 main.js 파일을 다운로드 받자고 명령을 해놓고 다시 파싱을 하다가 js 가 다운로드 완료되면 그 때 파싱을 멈추고 js를 실행하게 된다.
js 를 실행 후 멈췄던 html을 다시 파싱하게 되는데, 이 방법은 body 닫는태그에 있던것보다 js 다운 받는 것이 병렬적으로 일어나기 때문에 시간을 절약할 수 있지만 js가 html이 파싱되기도 전에 실행되기 때문에 만약 js 파일에서 querySelector로 DOM요소를 조작하려고 한다면 조작하려는 시점에 html의 우리가 원하는 요소가 아직 정의되어 있지 않을 수 있다는 위험 요소가 있고, html 파일을 파싱하는 동안에 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>
    <script defer src="main.js" ></script>
</head>
<body>
    
</body>
</html>

head태그 안에 script를 위치하고 defer라는 속성을 이용하여 작성하게 되면, main.js를 다운로드 받자는 명령만 시켜놓고 나머지 html을 끝까지 파싱하게되고, 마지막에 파싱이 끝난 후 다운로드 받은 js 파일을 실행하게 된다.
html을 파싱하는동안 필요한 js 파일을 다운로드 받아놓으면, 사용자에게 페이지를 먼저 다 보여준다음에 바로 이어서 js 파일을 실행한다.

만약 script가 a,b,c로 다수의 js 파일이 있다고 가정할 때,
async는 먼저 다운로드된 js 파일이 먼저 실행되기 때문에 정의된 js 파일의 순서와는 상관없이 크기에 따라 a,b,c 어떤 파일이 먼저 실행될 지 모른다는 단점이 있다.
defer는 파싱하는 동안 필요한 js 파일을 모두 다운로드 받아놓은 다음에 html 파싱이 끝나면 정의된 순서대로 js파일이 실행되기 때문에 내가 원하는대로 js 가 실행될 것이라는 것을 예상할 수 있다는 장점이 있다.

여러모로 살펴보았을때 head 안에 defer 를 사용하여 쓰는것이 가장 효율적이라고 할 수 있을 것 같다🥸
방법은 사용하는 사람마다 최선이라고 생각하는 범위에서 다양한 것 같다
head안에 defer와 함께 작성하는 사람도 있고, body 닫는 태그쪽에 작성하는 사람도 있다.
아직 배우는 단계라 뭐가 더 맞는건지 확실하진 않지만 배워가고 여러가지 경험하면서 나도 나만의 최선을 찾아나가야겠다🔥

profile
Sic Parvis Magna 🧩

0개의 댓글