[JS] 로딩속도개선 : <Script> 태그의 위치

유영·2024년 2월 19일
0

Web

목록 보기
3/4

문제점 및 해결

async를 사용해도
홈페이지 로딩속도가 느림 ->
slick에는 rel="preload"를 추가하고, slick을 제외한 나머지 script에 defer의 속성을 이용 -> slick이 작동하지 않음
jquery에 넣은 defer를 제거하니 slick 작동

Script 태그

<script> 태그의 위치는 아주 중요한 문제입니다.
물론 <html></html> 태그 사이에 두기만 하면 적용이 됩니다.
하지만 위치에 따라서 속도 차이가 있으며,
또 DOM이 완성되지 않은 상태에서 자바스크립트가 DOM을 조작하려고하면 에러가 발생합니다.

그래서 과연 어디에 위치해주는게 가장 좋은 방법인지 찾아보았고 정리하게 되었습니다.

브라우저 동작 방식

우선 script태그의 위치에 대해서 설명하기 전에 브라우저의 동작 방식에 대해서 알아봐야합니다.

  1. HTML 파일 읽기
  2. HTML문서를 한 줄 한 줄 순차적으로 파싱
  3. DOM 트리 만들기
  4. CSSOM 트리와 DOM 트리를 결합하여 렌더 트리 구축 (Attachment)
  5. 화면에 표시하기

이렇게 위의 순서대로 브라우저가 동작하게 되는데, HTML 문서를 한 줄씩 파싱하면서 DOM 생성 중 CSS를 로드하는<link> 태그 또는 <style> 태그를 만나면 DOM 생성을 잠시 중지한 후 CSS파싱의 결과물인 CSSOM을 생성하는 과정을 진행합니다.

그리고 마찬가지로 자바스크립트 코드를 로드하는 <script> 태그를 만나면 DOM 생성을 중지한 후 자바스크립트 엔진에 제어권을 넘겨서 작업을 실시한 후 자바스크립트 파싱이 끝나면 다시 DOM 생성을 시작하게 됩니다.
그렇기 때문에 <script>태그의 위치의 따라서 차이가 생기게 되는 것 입니다.


<위치에 따른 차이점과 결론>

1. <head> 태그 사이에 위치 (옵션 없음)

처음으로 소개할 방법은 <head> 태그 사이에 위치하는 방법입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
  <script src="./main.js"></script>
</head>
<body>
  <h1>head 태그 안으로 넣기</h1>
</body>
</html>

HTML 파싱 ▶️ HTML 파싱 정지 ▶️ JavaScript 파일 다운로드 후 실행 ▶️ HTML 이어서 파싱

<head>태그 사이에 위치하는 방법은 딱히 좋은 방법이라고 할 수 없습니다.
자바스크립트의 파일의 크기가 가볍다면 미비한 영향을 미치겠지만 크기가 무겁고, 인터넷의 속도가 느리다면 웹사이트를 보는 데까지 많은 시간이 소요된다는 단점이 생기기 때문입니다.
그리고 또한 DOM을 제어하고 조작하는 자바스크립트 코드가 있다면 오류가 발생할 수 있습니다.

2. <body> 끝, 즉 </body> 태그 앞에 위치

두 번째 방법은 <body> 끝, 즉 </body> 태그 앞에 위치하는 방법입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
</head>
<body>
  <h1>body 태그 끝에 넣기</h1>
  <script src="./main.js"></script>
</body>
</html>

HTML 파싱 ▶️ JavaScript 파일 다운로드 후 실행

아마 대부분의 경우에 제일 많이 위치하여 사용하는 방법일 겁니다.
자바스크립트 파일을 다운로드하기 전 HTML 코드를 모두 파싱 하기 때문에 사용자가 화면의 내용을 빨리 볼 수 있다는 장점이 있습니다.
하지만 HTML 코드가 자바스크립트 의존적인 웹사이트라면 사용자가 화면을 보기까지에는 똑같이 오랜 시간이 걸릴 수 있다는 단점이 있습니다.

3. <head> 태그 사이에 위치 + async 속성

세 번째 방법으로는 첫 번째 방식과는 동일하지만 async 속성을 추가하는 방법입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
  <script async src="./main.js"></script>
</head>
<body>
  <h1>async 속성을 추가해 head 태그 안으로 넣기</h1>
</body>
</html>

HTML 파싱 ▶️ JavaScript 파일 만나면 병렬적으로 다운로드 ▶️ JavaScript 파일 다운 완료되면 HTML 파싱 정지 ▶️ JavaScript 파일 실행 ▶️ HTML 이어서 파싱

async 속성을 추가하는 경우에는 자바스크립트 파일을 만나면 병렬 다운로드 되기 때문에 다운로드 시간을 절약해서 속도가 빨라질 수 있지만,
자바스크립트 파일이 실행이 될 때 잠시 HTML 파싱이 멈추기 때문에 첫 번째 방법에서의 문제점이 그대로 나타날 수 있습니다.

4. <head> 태그 사이에 위치 + defer 속성

마지막으로 defer 속성을 추가하여 태그 사이에 위치하는 방법입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
  <script defer src="./main.js"></script>
</head>
<body>
  <h1>defer 속성을 추가해 head 태그 안으로 넣기</h1>
</body>
</html>

HTML 파싱 ▶️ JavaScript 파일 만나면 병렬적으로 다운로드 ▶️ HTML 전체 파싱 후 JavaScript 파일 실행

defer 속성을 추가하면 위의 설명한 async의 방식과 같이 HTML 파싱하는 동안 자바스크립트 코드를 다운로드를 완료하고 파싱이 완료 되면 파일이 실행됩니다.
따라서 속도적인면에서는 가장 우세하다고 볼 수 있습니다.

async, defer 다수의 자바스크립트 로드

async, defer 두가지 속성의 경우에 HTML을 파싱하는 동안 자바스크립트 코드를 다운로드 한다는 공통점이 있지만 다수의 자바스크립트를 로드하는 경우 차이점이 더욱 크게 느껴집니다.

async

defer

참고
https://shape-coding.tistory.com/entry/JavaScript-Script-%ED%83%9C%EA%B7%B8%EC%9D%98-%EC%9C%84%EC%B9%98%EB%8A%94-%EC%96%B4%EB%94%94%EA%B0%80-%EC%A2%8B%EC%9D%84%EA%B9%8C

0개의 댓글