DOM 렌더링
- 브라우저가 HTML 문서를 파싱하여 DOM 트리를 생성하고 이를 기반으로 화면에 문서를 그리는 과정을 의미
- HTML 문서의 생명주기엔 다음과 같은 3가지 주요 이벤트가 관여
- DOMContentLoaded
- 브라우저가 HTML을 전부 읽고 DOM 트리를 완성하는 즉시 발생
- 이미지 파일(<img>)이나 스타일시트 등의 기타 자원은 기다리지 않음
- 단, HTML 문서에 <script> 태그가 포함되어 있고 defer나 async가 설정되지 않은 경우 스크립트 실행이 완료된 이후에 발생
- load
- HTML로 DOM 트리를 만드는 게 완성되었을 뿐만 아니라 이미지, 스타일시트 같은 외부 자원도 모두 불러오는 것이 끝났을 때 발생
- 일반적으로 이 이벤트는 페이지가 완전히 렌더링된 후 수행해야 할 초기화 작업에 사용
- beforeunload/unload
- 사용자가 페이지를 떠날 때 발생
- DOMContentLoaded
생명주기 이벤트 사용 상황
- DOMContentLoaded
- DOM이 준비된 것을 확인한 후 원하는 DOM 노드를 찾아 핸들러를 등록해 인터페이스를 초기화할 때
- load
- 이미지 사이즈를 확인할 때 등. 외부 자원이 로드된 후이기 때문에 스타일이 적용된 상태이므로 화면에 뿌려지는 요소의 실제 크기를 확인 가능
- beforeunload
- 사용자가 사이트를 떠나려 할 때, 변경되지 않은 사항들을 저장했는지 확인시켜줄 때
- unload
- 사용자가 진짜 떠나기 전에 사용자 분석 정보를 담은 통계자료를 전송하고자 할 때
DOMContentLoaded
- DOMContentLoaded 이벤트는 document 객체에서 발생
- 따라서 이 이벤트를 다루려면 addEventListener 사용
예제 코드
- DOMContentLoaded 핸들러는 문서가 로드되었을 때 실행되기 때문에 핸들러 아래쪽에 위치한 <img> 태그 뿐만 아니라 모든 요소에 접근 가능
- 하지만, 이미지 로드 되는 것을 기다리는 것이 아니기 때문에 사이즈가 0x0으로 표시 됨
- 실행 순서
- DOM이 준비되었습니다!
- 이미지 사이즈 : 0x0
- 이미지 로드
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<script>
function ready() {
alert('DOM이 준비되었습니다!');
// 이미지가 로드되지 않은 상태이기 때문에 사이즈는 0x0입니다.
alert(`이미지 사이즈: ${img.offsetWidth}x${img.offsetHeight}`);
}
document.addEventListener("DOMContentLoaded", ready);
</script>
<img id="img" src="https://en.js.cx/clipart/train.gif?speed=1&cache=0">
</body>
</html>
DOMContentLoaded와 scripts
- 브라우저는 HTML 문서를 처리하는 도중에 <script> 태그를 만나면 DOM 트리 구성을 멈추고 <script>를 실행
- 스크립트 실행이 끝난 후에야 나머지 HTML 문서를 처리
- <script>에 있는 스크립트가 DOM 조작 관련 로직을 담고 있을 수 있기 때문에 이런 방지책이 만들어졌음
- 따라서 DOMContentLoaded 이벤트 역시 <script> 안에 있는 스크립트가 처리되고 난 후에 발생
- 실행 순서
- 브라우저가 <script> 태그를 만나면 DOM 구성을 멈추고 해당 스크립트를 실행
- 첫 번째 <script>
- DOMContentLoaded 이벤트 리스너를 등록하지만, 아직 실행되지 않음
- 이 이벤트는 DOM 구성이 끝난 후 발생
- 두 번째 <script>
- 외부 스크립트 파일(lodash.js)을 다운로드하고 실행
- 다운로드가 완료될 때까지 다음 스크립트는 실행되지 않음
- 세 번째 <script>
- 외부 스크립트 실행 후 실행
- "라이브러리 로딩이 끝나고 인라인 스크립트가 실행되었습니다."라는 알림 발생
- DOM 구성이 완료되면 DOMContentLoaded 이벤트가 발생
- "DOM이 준비되었습니다!"라는 알림 발생
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
document.addEventListener("DOMContentLoaded", () => {
alert("DOM이 준비되었습니다!");
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.js"></script>
<script>
alert("라이브러리 로딩이 끝나고 인라인 스크립트가 실행되었습니다.");
</script>
</head>
<body>
</body>
</html>
DOMContentLoaded와 styles
- 외부 스타일시트는 DOM에 영향을 주지 않기 때문에 DOMContentLoaded는 외부 스타일시트가 로드되기를 기다리지 않지만 한 가지 예외가 존재
- 스타일시트를 불러오는 태그(<link>) 바로 다음에 스크립트(<script>)가 위치하면 이 스크립트는 스타일시트가 로드되기 전까지 실행되지 않음
- 스크립트에서 스타일(예: getComputedStyle)에 의존하는 작업을 수행할 가능성이 있기 때문에 발생하는 제약
- 스타일시트 로드와는 무관하게, 모든 스크립트가 실행된 후에야 DOMContentLoaded 이벤트가 발생
- 아래 예제와 같은 상황에서는 스타일시트가 로드되길 기다리므로, 자연스럽게 DOMContentLoaded도 스타일 로드 완료 이후에 발생
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<link type="text/css" rel="stylesheet" href="style.css">
<script>
alert(getComputedStyle(document.body).marginTop);
</script>
</body>
</html>
브라우저 내장 자동완성
- Firefox, Chrome, Opera의 폼 자동완성(form autofill)은 DOM 트리가 완성된 후 (DOMContentLoaded) 자동 완성 처리
- 페이지에 아이디와 비밀번호를 적는 폼이 있고, 브라우저에 아이디, 비밀번호 정보가 저장되어 있다면 DOMContentLoaded 이벤트가 발생할 때 인증 정보가 자동으로 채워짐
→ 사용자가 자동 완성을 허용했을 경우 - 따라서 실행해야 할 스크립트가 길어서 DOMContentLoaded 이벤트가 지연된다면 자동완성 역시 뒤늦게 처리
- 브라우저 자동 완성 기능을 켜 놓은 사용자라면 특정 사이트에서 자동 완성이 늦게 처리되는 걸 경험 해보았을 텐데 이런 사이트에선 페이지 로딩이 다 끝난 후에야 아이디나 패스워드 같은 브라우저에 저장한 정보가 폼에 뜸
- 이런 지연이 발생하는 이유는 DOMContentLoaded 이벤트가 실행되는 시점 때문임
window.onload
- window 객체의 load 이벤트는 스타일, 이미지 등의 리소스들이 모두 로드되었을 때 실행
- load 이벤트는 onload 프로퍼티를 통해서도 사용 가능
- 다음 예시에서 window.onload는 이미지가 모두 로드되고 난 후 실행되기 때문에 이미지 사이즈가 제대로 출력되는 것을 확인 가능
- 실행 순서
- 이미지 로드
- 페이지 전체가 로드되었습니다.
- 사이즈 : 177 x 160
<!DOCTYPE html>
<script>
window.onload = function() { // window.addEventListener('load', (event) => {와 동일합니다.
alert('페이지 전체가 로드되었습니다.');
// 이번엔 이미지가 제대로 불러와 진 후에 얼럿창이 실행됩니다.
alert(`이미지 사이즈: ${img.offsetWidth}x${img.offsetHeight}`);
};
</script>
<img id="img" src="https://en.js.cx/clipart/train.gif?speed=1&cache=0">
</html>
window.onunload
- window 객체의 unload 이벤트는 사용자가 페이지를 떠날 때 즉, 페이지가 완전히 닫히거나 새 페이지로 이동할 때 실행
- 이벤트에서 실행할 수 있는 작업은 제한적
Ex) 팝업창을 닫거나 자원을 정리하는 등의 간단한 작업을 수행 - 비동기 작업(예: AJAX 요청)은 완료되지 않을 수 있기 때문에, 페이지가 완전히 떠나기 전에 데이터를 보내는 데 적합하지 않음
- navigator.sendBeacon() 메서드는 비동기적으로 데이터를 서버로 전송하는 데 사용
- 이는 페이지 이동이나 종료 중에도 데이터를 서버로 안전하게 전송 가능하게 해줌
- sendBeacon()은 데이터를 백그라운드에서 보내므로 페이지가 종료되는 데 딜레이를 주지 않음
- 이 메서드는 정확하게 전송할 수 있는 데이터를 최대 64KB까지 보낼 수 있으며, 주로 분석 데이터를 보내는 데 유용
let analyticsData = { /* 분석 정보가 담긴 객체 */ };
window.addEventListener("unload", function() {
navigator.sendBeacon("/analytics", JSON.stringify(analyticsData));
};
- 요청은 POST 메서드로 전송
- 요청 시 문자열뿐만 아니라 폼이나 fetch에서 설명하는 기타 포맷들도 보낼 수 있음
대개는 문자열 형태의 객체가 전송 - 전송 데이터는 64kb를 넘을 수 없음
window.onbeforeunload
- 사용자가 페이지를 떠나기 전에 발생하는 이벤트
- 이 이벤트는 사용자가 페이지를 닫거나 새로 고침할 때, 또는 다른 페이지로 이동할 때 트리거 됨
- 이 이벤트는 주로 사용자가 아직 저장되지 않은 데이터를 잃어버릴 수 있는 경우 경고를 표시하는 데 사용
<body>
<h1>페이지를 떠나기 전에 경고하기</h1>
<script>
window.onbeforeunload = function(event) {
// 사용자에게 경고 메시지 표시
event.returnValue = "페이지를 떠나면 저장되지 않은 변경 사항이 사라집니다. 정말 떠나시겠습니까?";
// returnValue를 설정해야 브라우저가 경고 메시지를 표시
};
</script>
</body>
- 브라우저는 onbeforeunload 이벤트에서 event.returnValue를 설정하면, 사용자가 페이지를 떠날 때 페이지를 떠나면 변경 사항이 저장되지 않음을 알리는 기본 경고 메시지를 자동으로 표시
- Chrome, Firefox, Edge와 같은 주요 브라우저는 사용자가 페이지를 떠날 때 onbeforeunload 이벤트를 처리하면 기본적으로 커스터마이즈된 메시지를 무시하고, 자체적으로 표시하는 경고 메시지를 사용
- 이는 보안 및 사용자 경험을 고려한 브라우저의 제한 사항
'Language > Javascript' 카테고리의 다른 글
[ES6+] ES7 ~ ES13 추가 기능 (1) | 2024.12.26 |
---|---|
[개념] ES6이란? (1) | 2024.12.24 |
[Javascript] DOM (Document Object Model)의 개념 (0) | 2024.12.09 |
[Javascript] 비동기 프로그래밍 [Callback, Promise, async/await] (0) | 2024.12.09 |
[Javascript] Javascript 동작 원리 [동기, 비동기] (0) | 2024.12.06 |