[JavaScript] html 파일 속 script는 어디서 실행해야할까?

muz·2022년 1월 12일
0
post-thumbnail

html파일과 javascript 파일 연결하기 ⛓

HTML, CSS까지 배우고, JavaScript를 배우기 시작한 분이라면 누구나 한번쯤은 이런 고민을 해보았을 것이다. 필자도 매번 궁금해했던 것이었다 ! 🙄

HTML과 JavaScript를 연결하는 방법은 다양하다. 보통 이 두가지 방법을 사용한다.
1. HTML 파일 내에서 <script> </script> 태그를 이용하여 JavaScript 코드를 작성하는 방법
2. 따로 .js 파일을 만들고 JavaScript 파일과 HTML 파일을 연결하는 방법

그런데, 공부를 하다보면 누구는 <head> </head> 태그 안에서 연결을 하기도 하고, 또 누구는 <body> </body>안에서 연결하기도 한다.

script 연결 위치에 따라 뭐가 달라지긴 해요? 🤔

정답부터 말하자면 달라진다. 연결 위치가 은근히 큰 영향을 미친다.

1. <head></head> 안에 script가 포함된 경우

<!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>

  • 코드 실행 순서
    1. html 파일을 한 줄씩 파싱함
    2. 파싱하다가 script 태그를 만나면 파싱을 멈추고 main.js파일을 다운받음
    3. 다운로드가 끝나면 .js를 바로 실행하고, 실행이 끝나면 다시 HTML 파일을 파싱
  • But...
    • 만약 인터넷이 굉장히 느리고, .js의 용량이 굉장히 크면 사용자가 내 웹사이트를 보기까지 굉장히 오랜 시간이 걸릴 것

      ⇒ 때문에 <head>안에 script를 포함하는 것은 좋지 않은 방법

2. <body>태그 안쪽 마지막 부분에 script를 추가한 경우

<!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>
		<!-- 이곳에서 포함됨 -->
    <script src="./main.js"></script>
</body>
</html>

  • 코드 실행 순서
    1. html 파일을 쭉 파싱해서 페이지 준비가 끝난 후, script태그를 만나면 서버에서 .js를 다운로드받고 다운이 끝나면 .js를 실행함
  • 장점
    • 사용자가 기본적인 HTML의 컨텐츠를 빠르고 볼 수 있음
      .js를 받기도 전에 이미 페이지가 준비되어 있기 때문
  • 단점
    • 만약 내 웹사이트가 .js에 굉장히 의존적인 경우

    • (사용자가 의미있는 컨텐츠를 보려면 .js를 이용해 서버에서 데이터를 받아오는 경우)

    • (.js에서 DOM 요소를 꾸며주는 게 많은 경우)

      ⇒ 사용자가 정상적으로 웹사이트를 보기까지 오랜 시간이 소요됨

3. <head> + async 이용 시

📢 async는 boolean 타입의 속성값이기 때문에 선언하는 것만으로도 true로 설정되어 async를 사용할 수 있음

<!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>
		<!-- async 추가 부분-->
    <script async src="./main.js"></script>
</head>
<body>
    
</body>
</html>

  • 코드 실행 순서
    1. html을 파싱하다가 script 태그에서 async를 만나면, 병렬로 .js파일을 다운로드 받기 시작
    2. html 파싱과 동시에 .js파일을 다운로드 받다가, .js파일의 다운로드가 끝나면, html 파싱을 잠시 멈춤
    3. 파싱을 멈춘 동안 .js를 실행하고, 실행이 끝나면 다시 남은 html 파일을 파싱
  • 단점
    • html 파싱이 완료되기 전에 .js파일이 실행되므로, .js에서 querySelector로 DOM요소 조작 시 우리가 원하는 시점에 DOM 요소가 아직 정의되지 않았을 수도 있음

    • html을 파싱하는 동안 언제든지 .js를 실행하기 위해 멈출 수 있음

      → 사용자가 페이지를 보기 전까지 또 다소 시간이 걸릴 수 있음

  • 장점
    • body 태그 끝에 사용하는 것 보다 fetching(다운로드)이 병렬적으로 일어나므로, 다운로드 받는 시간 절약 가능

4. <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>
		<!-- defer을 추가한 부분 -->
    <script defer src="./main.js"></script>
</head>
<body>
    
</body>
</html>

  • 코드 실행 순서
    • html을 파싱하다가 script 태그defer을 만나면 .js파일 다운로드를 시작하고, 계속 html 파일을 파싱함
    • html 파싱이 끝난 직후 .js를 실행

script 다운 시, asyncdefer의 차이 🚨

1. 여러 개의 파일을 async로 가져올 때

📢 async를 사용하면 정의된 스크립트의 순서와 상관없이, 먼저 다운로드 된 .js파일부터 실행함
⇒ 만약 내 프로그램이 .js 실행 순서에 의존된다면 문제 발생 가능

<!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>
    	<!-- async 추가한 부분 -->
    <script async src="./a.js"></script>
    <script async src="./b.js"></script>
    <script async src="./c.js"></script>
</head>
<body>
        
</body>
</html>

2. 여러 개의 파일을 defer로 가져올 때

📢 html을 파싱하다가 defer를 만나면 각 .js파일을 다운로드하고, 파싱이 끝나면 정의된 순서대로 다운로드한 .js파일들을 실행함

<!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>
  		<!-- defer 추가한 부분 -->
    <script defer src="./a.js"></script>
    <script defer src="./b.js"></script>
    <script defer src="./c.js"></script>
</head>
<body>
        
</body>
</html>

profile
Life is what i make up it 💨

0개의 댓글