HTML 파일에서 JS 파일을 가져올 때 효과적으로 가져오는 방법을 알아보자.
HTML 파일은 위에서 아래로 파싱하며 소스를 읽어들인다. 또한 script 태그를 만나면 파싱을 잠시 멈추고, 스크립트 파일을 가져온 뒤(script fetch) 해당 스크립트를 실행(script execution)하는게 기본적인 속성이다.
1. 가장 기본적인 방법 : html 파일 <head> 에서 <script> 태그를 통해 가져올 수 있다.
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
....
<script src="script.js"></script>
....
</head>
<body>
<button id="btn">버튼</button>
....
</body>
</html>
//script.js
let btn = document.querySelector('#btn');
btn.addEventListener('click', function () {
alert('hi');
});
위 예시에서 버튼을 하나 만들고, script.js 파일에서 클릭 이벤트에 대한 스크립트를 작성했다. 이 버튼을 클릭하면 작성한 스크립트가 실행될 것 같지만 실제로는 Cannot read properties of null (reading 'addEventListener') 오류가 발생한다.
스크립트 파일 실행 시 querySelector로 btn을 접근하려고할 때, 아직 html 파싱이 버튼까지 일어나지 않은 상태이기 때문에 해당 DOM 요소를 가져올 수 없어 오류가 난 것이다.
이런 오류를 해결하기 위해서는 DOM 요소가 파싱된 후에 스크립트 파일이 실행되도록 해야 한다.
2. <script> 태그를 <body> 최하단으로 이동하는 방법
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
....
</head>
<body>
<button id="btn">버튼</button>
....
<script src="script.js"></script> //스크립트 태그를 최하단으로 이동
</body>
</html>
위에서부터 파싱하는 html 속성에 따라 DOM 요소들을 모두 파싱한 후에 스크립트를 읽게되면 문제 없이 스크립트가 실행될 것이다.
3. load 이벤트 리스너 등록 : HTML 파싱 > DOM 생성 > 외부 콘텐츠 로드 > 이벤트 발생
//script.js
window.onload = function () {
let btn = document.querySelector('#btn');
btn.addEventListener('click', function () {
alert('hi');
});
}
혹은, load 이벤트 리스너를 등록하는 방법이 있다. window.onload 는 html 파싱, dom 생성 그리고 외부 콘텐츠 (이미지, script, css 등) 모든 것이 로드된 후 발생하는 이벤트이다. <script>태그가 기존과 같이 <head>에 있더라도, script 파일 내에서 모든 소스를 window.onload = function() {} 안에 넣는다면, 위와 같은 오류가 발생하지 않을 것이다.
4. DOMContentLoaded 이벤트 리스너 등록 : HTML 파싱 > DOM 생성 > 이벤트 발생
//script.js
document.addEventListener('DOMContentLoaded', function () {
let btn = document.querySelector('#btn');
btn.addEventListener('click', function () {
alert('hi');
});
}
이 때 외부 콘텐츠까지 기다리는 것이 비효율적일 수 있다. 그럴 때에는 html 파싱, dom 생성 후 발생하는 이벤트인 DOMContentLoaded 이벤트를 사용할 수 있다.
5. (HTML5) defer 속성 사용
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
....
<script src="script.js" defer></script>
....
</head>
<body>
<button id="btn">버튼</button>
....
</body>
</html>
HTML5에서 등장한 defer와 async 속성을 통해 비동기로 script 로드가 가능해졌다.
defer 속성을 주면 HTML 파싱이 진행되다가 <script> 태그를 만나도 파싱이 중단되지 않고, 비동기로 해당 JS 파일을 불러온다. 그리고 HTML 파싱이 완료된 후, JS 코드를 실행한다.
6. (HTML5) async 속성 사용
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
....
<script src="script.js" async></script>
....
</head>
<body>
<button id="btn">버튼</button>
....
</body>
</html>
async의 경우 defer와 마찬가지로 HTML 파싱이 진행되다가 <script> 태그를 만나도 파싱이 중단되지 않고, 비동기로 해당 JS 파일을 불러온다. 하지만 HTML 파싱이 완료되지 않았더라도, 먼저 로딩되는 JS 파일부터 실행이 시작된다. JS 파일을 실행할 때는 HTML 파싱이 잠시 중단된다.
따라서 처음에 DOM 요소를 가져오지 못한 오류가 이 때에도 발생할 수 있어, 꼭 필요한 경우에만 이 async 속성을 사용한다.
이 포스팅은 프론트엔드 날개달기: Vue, React 배우기 전에 꼭 알아야하는 지식 강의를 수강하며 작성되었습니다.
[지금 무료] 프론트엔드 날개달기: Vue, React 배우기 전에 꼭 알아야하는 지식 | 짐코딩 - 인프런
짐코딩 | 이 강의를 통해 Webpack, NPM 등 프론트엔드 개발자가 되기 전에 꼭 알아야할 지식을 탄탄히 다질 수 있습니다., 백그라운드 지식을 확실히 알아야,진짜 프론트엔드 개발자가 될 수 있어요
www.inflearn.com
'JavaScript' 카테고리의 다른 글
[JavaScript] 즉시 실행 함수 (IIFE) (0) | 2024.06.13 |
---|---|
[JavaScript] this 이해하기 (this, window, bind) (0) | 2024.06.10 |
[JavaScript] 브라우저 객체 모델 BOM (Browser Object Model) (1) | 2024.06.06 |
[JavaScript] 문서 객체 모델 DOM (Document Object Model) (0) | 2024.05.30 |
레이어 팝업 vs 모달 팝업 (0) | 2024.04.03 |