프론트엔드 개발자로서 성능 최적화는 중요한 과제입니다. HTML 문서에서 JavaScript 파일을 가져올 때, script
태그의 기본 동작과 함께 HTML5에 추가된 defer
및 async
속성을 활용하면 로딩 속도를 개선하고 성능을 최적화할 수 있습니다. 이번 포스팅에서는 각각의 개념과 올바른 사용 예시를 간단하게 알아봅시다.
🔖 HTML 코드는 위에서부터 아래로 파싱됩니다.
script 태그의 기본 동작
HTML로 파일을 작성할 때 script태그를 사용해 JS 파일을 불러올 수 있습니다. 브라우저가 HTML 파일을 위에서부터 아래로 순차적으로 파싱하면서 <script>
태그를 만나면 HTML 문서의 파싱을 멈추고 JavaScript 파일을 다운로드하여 실행한 후 나머지 HTML을 계속 파싱합니다.
<script src="app.js"></script>
🔧 script 태그의 문제점 알기
script 태그를 head 태그에 위치하거나 body 태그 최상단에 넣을 경우 HTML이 다 파싱되기 전에 DOM요소를 제어하려는 script태그 내에 js 코드를 만나게 되면서 문제가 발생하게 됩니다. 또한 렌더링 과정에서 대규모 JavaScript파일이나 CSS파일과 같은 특정 리소스를 다운로드 될 때 해당 파일이 실행될 때까지 HTML 문서의 파싱이 멈추게 되면서 렌더링이 멈추는 현상이 발생하게 됩니다 ( = 렌더링 블로킹 문제 발생) 또한 스크립트 로드와 실행 중 HTML 파싱이 멈춘다게되면서 대규모 스크립트 파일이 로드되면 사용자 경험(UX)에 저하시킵니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<script src="app.js"></script>
</head>
<body>
<div id="content">이곳에 텍스트가 추가됩니다.</div>
</body>
</html>
// app.js
document.getElementById('content').textContent = 'Hello, world!';
해당 코드의 문제점은 외부 JavaScript 파일(app.js)이 DOM 요소 #content를 조작하려 하지만, HTML이 아직 완전히 파싱되지 않아 DOM 요소를 찾을 수 없어 문제가 발생합니다. 해당 문제를 해결하는 방법은 크게 두 가지가 있는데, script
태그를 body코드 최 하단에 위치시키거나 DOMContentLoaded
이벤트를 활용하거나 defer
, async
속성을 사용하는 방법이 있습니다.
✔️ script 로드 해결 방법
HTML5에 이전에는 body 태그 최 하단에 <script>
태그를 넣거나 load
이벤트를 사용해 DOM 준비 이후 스크립트를 실행하여 해결하였습니다. 하지만 HTML5 에서 defer
, async
속성으로 비동기 script
로드가 가능해져 이러한 문제를 더 간단하게 해결할 수 있게 되었습니다. 이전 해결방식으로 순차적으로 알아보겠습니다.
1. body 태그 최 하단에 script 태그 넣기
<script>
태그를 body 태그 끝에 배치해 HTML 파싱이 끝난 후 스크립트 로드되도록 합니다.
<!DOCTYPE html>
<html lang="ko">
<head>
</head>
<body>
<div id="content">이곳에 텍스트가 추가됩니다.</div>
<script src="app.js"></script>
</body>
</html>
2. load 이벤트 리스너 등록하기
window.onload
: HTML, CSS, 이미지 등 모든 리소스가 로드된 후 실행됩니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>window.onload 예제</title>
</head>
<body>
<img src="https://via.placeholder.com/150" alt="이미지 예제" />
<button id="btn">클릭하세요</button>
<script>
window.onload = function () {
const btn = document.getElementById('btn');
btn.addEventListener('click', function () {
alert('Hello, window.onload!');
});
};
</script>
</body>
</html>
DOMContentLoaded
: HTML 파싱이 완료된 후 외부 리소스(이미지, 스타일시트 등) 로딩은 기다리지 않아 즉시 스크립트를 실행할 수 있습니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>DOMContentLoaded 예제</title>
</head>
<body>
<button id="btn">클릭하세요</button>
<script>
document.addEventListener('DOMContentLoaded', function () {
const btn = document.getElementById('btn');
btn.addEventListener('click', function () {
alert('Hello, DOMContentLoaded!');
});
});
</script>
</body>
</html>
DOMContentLoaded과 window.onload의 차이
특징 | DOMContentLoaded | window.onload |
---|---|---|
실행 시점 | DOM이 준비된 직후 | 모든 리소스 로드 완료 후 |
속도 | 더 빠름 | 느림 |
외부 리소스 의존성 여부 | 없음 | 있음 |
사용 사례 | DOM 조작 작업 | 이미지나 스타일 로드 후 작업 |
- DOM 준비만 필요하다면 DOMContentLoaded, 전체 리소스 로드 후 작업이 필요하다면 window.onload를 사용할 수 있습니다. 상황에 맞게 script파일을 분리하여 사용하도록 합니다.
🔖 HTML5의 script 로드 해결 방법
HTML5에서는 defer
async
속성을 통해 비동기 script
로드로 해결할 수 있습니다.
✔️ defer 속성
defer는 스크립트를 비동기로 다운로드하면서도 HTML 파싱을 차단하지 않는 속성입니다.
HTML 파싱이 완료된 후, 스크립트가 정의된 순서대로 실행됩니다.
<script src="app.js" defer></script>
특징
- 스크립트 파일 다운로드는 비동기로 이루어짐.
- HTML 파싱 완료 후 실행되므로 DOM이 완전히 준비된 상태에서 스크립트 실행 가능.
- 스크립트가 정의된 순서를 보장함.
사용 예시
- DOM 의존성이 있는 스크립트(예: DOM 조작 코드).
- 실행 순서가 중요한 여러 스크립트.
✔️ async 속성
async는 스크립트를 비동기로 다운로드하면서도, HTML 파싱과 별개로 다운로드가 완료되는 즉시 실행합니다.
이는 defer와 달리 스크립트 실행 순서가 보장되지 않습니다.
<script src="analytics.js" async></script>
특징
- 스크립트 파일 다운로드는 비동기로 이루어짐.
- 다운로드가 완료되면 즉시 실행되므로 HTML 파싱이 일시적으로 멈출 수 있음.
- 실행 순서가 중요하지 않은 스크립트에 적합 ( 실행 순서가 보장되지 않아 독립적인 스크립트에 적합 )
사용 예시
- 실행 순서가 중요하지 않은 광고 코드나 분석 도구 스크립트에 적합.
✔️ defer와 async를 활용하여 내 웹페이지 최적화하기
- defer는 대부분의 경우 DOM 조작과 관련된 코드에 적합합니다.
- async는 Google Analytics와 같은 외부 도구를 로드할 때 유용하게 사용할 수 있습니다. 외부 의존성이 없는 코드에 사용에 적합합니다.
- Webpack, Vite 등의 번들링 도구를 통해 파일 크기를 줄이고 로딩 속도를 개선할 수 있습니다.
🎁 마무리
defer
와 async
는 프론트엔드 개발자가 알아야 할 중요한 최적화 도구입니다. 적합한 속성을 사용해 렌더링 블로킹을 방지하고 페이지 로딩 속도를 개선하여 더 나은 UX를 제공할 수 있습니다. 프로젝트마다 상황에 맞는 속성을 선택해 효율적인 최적화를 달성해보세요! 💪
참고
'Web Frontend' 카테고리의 다른 글
API 쉽게 이해하기, API 어디까지 쓰이는걸까? (0) | 2025.01.05 |
---|---|
JavaScript this 이제 헷갈리지말자 (0) | 2025.01.05 |
DOM과 BOM 차이 바로 알기 (0) | 2025.01.04 |
JS 알고리즘 테스트 환경 VS code로 세팅하기 (0) | 2024.08.22 |
객체 지향 프로그래밍, 프로토타입 이해하기 (0) | 2024.08.02 |