브라우저는 다음과 같은 과정을 거쳐 HTML 문서를 보여줍니다.
이 과정 중에 발생하는 이벤트는 다음과 같습니다.
DOMContentLoaded: DOM 트리 완성 즉시 발생, 기타 자원의 로딩은 기다리지 ❌load: DOM 트리도 완성되고, 외부 자원도 모두 불러오는 게 끝나면 발생beforeunload: 사용자가 다른 페이지로 이동하려 하거나 창을 닫으려 할 때 발생unload: 사용자가 페이지를 떠날 때(문서를 완전히 닫을 때) 발생각 이벤트는 다음과 같은 의미를 가집니다.
DOMContentLoaded: DOM 이 다 만들어졌으므로 원하는 DOM 노드 참조 가능load: 스타일이 적용된 상태이므로 화면이 나타난 요소의 실제 크기 확인 가능beforeunload: 사용자에게 변경 사항 저장 등을 확인함unload: 사용자 분석 정보를 전송할 때 사용DOMContentLoaded 이벤트는 document 객체에서 발생하며
문서가 로드되었을 때 핸들러가 실행됩니다.
DOMContentLoaded 이벤트에는 몇 가지 특징이 있습니다.
<script> 안 스크립트가 처리되고 난 후에 이벤트 발생 (스크립트가 이벤트를 막음)<script> 를 만나면 DOM 트리 구성을 멈추기 때문<script> 가 있는 경우, 스크립트에서 스타일을 사용할 수도 있으므로 스타일시트가 다 로드되어야 스크립트 실행DOMContentLoaded 이벤트가 발생할 때 실행됨문서가 완전히 로드된 후에 설정된 DOMContentLoaded 핸들러는 실행되지 않습니다.
DOMContentLoaded 이벤트가 발생하지 않기 때문이죠.
하지만 문서가 로드되었는지 아닌지 상태는 document.readyState 프로퍼티로 확인할 수 있습니다.
프로퍼티는 다음과 같은 세 종류의 값을 가집니다.
loading: 문서를 불러오는 중일 때interactive: 문서가 완전히 불러와졌을 때complete: 문서를 비롯한 이미지 등의 리소스들도 모두 불러와졌을 때이렇게 프로퍼티의 값을 읽고 상황에 따라 동작을 제시하면 됩니다.
function work() { /*...*/ }
if (document.readyState == 'loading') {
// 아직 로딩 중이므로 이벤트를 기다립니다.
document.addEventListener('DOMContentLoaded', work);
} else {
// DOM이 완성되었습니다!
work();
}
load, unload, beforeunload 이벤트는 window 객체에서 발생합니다.
onload / onunload / onbeforeunload 프로퍼티로 핸들러를 등록할 수 있습니다.
window.onbeforeunload = function() {
return false;
};
이렇게 false 를 반환하거나 addEventListener 로 등록한 핸들러에서 event.preventDefault() 를 호출하면 사용자에게 떠날 것인지 묻는 확인 메시지를 표시합니다.
스크립트들은 HTML 보다 양이 많아 다운로드에 시간이 오래 걸리죠.
브라우저가 <script> 태그를 만나면 DOM 생성을 멈춰야 한다는 점에서 다음과 같은 문제가 발생합니다.
이런 문제를 피하기 위한 가장 간단한 방법은 스크립트를 body 의 맨 아래에 놓는 것입니다.
<body>
... 스크립트 위 콘텐츠들 ...
<script src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>
</body>
이러면 스크립트 내에서 다른 DOM 요소에 자유롭게 접근할 수 있고, 스크립트를 다운받기 전에 페이지를 보여줄 수 있으니까요.
하지만 문서 다운 이후 또 스크립트 다운 과정을 거치느라 전체 리소스 다운까지 완료되는 시간이 매우 길어질 겁니다.
이런 문제는 <script> 태그에 defer 와 async 속성을 추가하여 해결합니다.
브라우저는 defer 속성이 있는 스크립트는 백그라운드에서 다운합니다.
따라서 스크립트 다운 중에서 HTML 파싱을 멈추지 않습니다.
다만 스크립트는 페이지 구성이 끝난 후 실행됩니다. (그 전까진 실행 지연)
<script defer src="..."></script>
이를 지연 스크립트라고 하며 DOM 이 준비된 후, DOMContentLoaded 이벤트 발생 전에 실행됩니다.
DOMContentLoaded 이벤트가 지연 스크립트가 실행되길 기다리기 때문입니다.
DOM 트리가 완성되고 지연 스크립트가 실행된 후에 DOMContentLoaded 이벤트가 발생합니다.
DOMContentLoaded 이벤트는 DOM 완료, 지연 스크립트 실행 후에 발생async 속성이 붙은 스크립트는 비동기 스크립트로, 역시나 백그라운드에서 다운로드됩니다.
따라서 브라우저는 비동기 스크립트가 다운되는 동안 DOM 을 생성하고 콘텐츠를 처리, 출력할 수 있습니다.
defer 와 달리, async 스크립트와 DOMContentLoaded 는 서로를 기다리지 않습니다.
비동기 스크립트 실행 전에 이벤트가 발생할 수도, 실행 후에 발생할 수도 있죠.
DOMContentLoaded 이벤트 발생 전, 후에 상관 없이 실행