웹 페이지 로딩 최적화: script vs script async vs script defer의 차이점

장성우·2024년 1월 2일

웹 성능 최적화

목록 보기
2/2
post-thumbnail

웹사이트의 성능을 향상시키는 것은 중요하다. 페이지의 로딩 속도와 콘텐츠 로딩속도가 사용자 경험에 영향을 미치기도 하고, Google의 연구에 따르면 FID(First Input Delay), CLS(Cumulative Layout Shift) 등의 성능을 개선하면 페이지 이탈률이 24% 감소한다고 한다.

보고서 링크
https://blog.chromium.org/2020/05/the-science-behind-web-vitals.html

이러한 성능 지표를 개선하는 한 방법은 JavaScript 로딩 전략을 최적화하는 것이다. <script>, <script async>, <script defer>는 페이지 로딩 속도에 영향을 미치는 스크립트 태그 옵션들이다. 이 세 가지 옵션의 동작 방식과 각기 다른 상황에서 어떤 옵션을 선택해야 하는지 알아보자.

<script> 만 사용할 경우

  • 위치: <head> 또는 <body>안에 있을 수 있다.
  • 동작: 옵션없이 기본 script 태그만 사용할 경우 브라우저는 script 태그를 만나게 되면 HTML 파싱을 중단하고, script를 다운로드하고 실행한 후에 HTML 파싱을 다시 시작한다.
  • 사용: 페이지가 script에 의존적인 경우(script가 DOM 요소를 조작하고 해당 요소들이 script 이전에 페이지에 존재하는 경우)
  • 주의할 점
    1.이 방법은 페이지의 로딩 시간을 지연시킬 수 있으므로, script가 매우 필요한 경우에만 사용해야 한다.
    2.script의 크기가 크고 많다면 다운로드와 실행에 많은 시간이 걸릴 수 있다. 그래서 이 경우에는<head>보다는 <body> 태그 끝에 위치시키는 게 좋다.

<script async>

  • 위치: 주로 <head>태그안에 위치한다.
  • 동작: script는 HTML 파싱되는 동안 비동기적으로 다운로드된다. script는 다운로드가 완료되면 현재 진행 중인 HTML 파싱을 잠시 중단하고 즉시 script를 실행한다. script 실행이 끝난 후에 HTML 파싱이 바로 다시 시작된다.
  • 사용: 외부 script를 불러올 때 사용한다. 그리고 script 실행 순서가 중요하지 않은 경우, script가 초기 렌더링에 의존적이지 않은 경우에 적합하다.
  • 장점: 페이지의 로딩 속도에 영향을 주지 않으면서 script를 비동기적으로 로드할 수 있다.
  • 주의할 점
    1. 외부 script를 불러오는 것이 아니라 Inline Script에 async속성을 사용하면 무시된다. Inline Script는 HTML 문서가 파싱될 때 해당 위치에서 즉시 실행되기 때문이다.
    2. 그리고 HTML 파싱 중간에 script의 다운로드가 끝나면 script가 바로 실행될 수 있다. 이때 아직 DOM요소가 준비되지 않았을 수 있으므로, DOM 조작이 필요한 script에는 적합하지 않을 수 있다.
    3. <script async>은 다운로드가 완료되는 즉시 실행되기 떄문에 script가 여러개인 경우 이들의 실행순서가 보장되지 않는다.따라서 <script async>를 여러 개 사용할 경우 script 간의 의존성을 먼저 확인하고, 가능한 한 각 script가 독립적으로 기능하도록 하여야 한다.

<script defer>

  • 위치: 주로 <head>태그안에 위치한다.

  • 동작: script의 다운로드와 HTML 파싱이 병렬로 진행된다. async와 달리 HTML 파싱이 전부 끝난 후 DOMContentLoaded 이벤트가 발생하기 바로 전에 실행된다.

  • 사용: 외부 script를 불러올 때 사용한다. DOM이 준비된 후 실행되기 때문에 DOM 조작이 필요한 script에 적합하다.

  • 주의할 점
    1. 외부 script를 불러오는 것이 아니라 Inline Script에 defer속성을 사용하면 무시된다. Inline Script는 HTML 문서가 파싱될 때 해당 위치에서 즉시 실행되기 때문이다.
    2. 브라우저는 <script defer> 태그를 발견한 순서대로 script를 실행하기 때문에, 서로 의존성을 가진 여러 개의 script가 있다면 올바른 순서로 배치하는 것이 중요하다. 이렇게 하면 script들이 의도한 순서대로 실행될 수 있다.


index.html

<!DOCTYPE html>
<html lang="en">
 <head>
   <meta charset="UTF-8" />
   <title>Script Loading Demo</title>
   <script>
     console.log("1. Without async or defer, in head");
   </script>
   <script async src="async-script.js"></script>
   <script defer src="defer-script.js"></script>
 </head>
 <body>
   <script>
     console.log("2. Without async or defer, in body");
   </script>
   <script>
     // HTML이 완전히 로드되었을 때(DOM트리가 구성되었을 때) 발생
     document.addEventListener("DOMContentLoaded", function () {
       console.log("4. DOMContentLoaded event raised");
     });
   </script>
   <script>
     // 모든 요소(이미지, 스타일, 폰트, 스크립트 등)가 로드되었을 때 발생
     window.onload = function () {
       console.log("5. Load event raised");
     };
   </script>
 </body>
</html>

async-script.js

console.log("3. Async script loaded");

defer-script.js

console.log("3. Defer script loaded");

만약 부정확한 내용이 있다면 댓글로 알려주세요. 수정하겠습니다.

profile
HiHeLlo!1

0개의 댓글