브라우저는 HTML을 어떻게 불러올까? DOM 생성부터 페이지 종료까지 전 과정을 알아봅니다
웹페이지 하나가 눈앞에 보이기까지, 브라우저 안에서는 정말 많은 일이 일어나고 있습니다.
단순히 HTML 파일 하나를 불러오는 게 아니라, 내부에 있는 수많은 요소들과 외부 리소스를 파싱하고 실행하면서 페이지가 완성되는데요. 이 복잡한 과정을 HTML의 생명주기(Lifecycle)라고 부를 수 있습니다.
HTML 자체는 자바스크립트처럼 생명주기 훅(hook)을 직접 제공하지 않지만, 브라우저가 HTML을 어떻게 읽고 처리하는지, 그리고 어떤 이벤트가 발생하는지를 이해하면 더 나은 사용자 경험과 성능을 만들 수 있습니다.
이번 글에서는 HTML이 브라우저에서 어떤 식으로 처리되는지 단계별로 알아보겠습니다.
1. HTML 파싱: 브라우저는 HTML을 어떻게 읽을까?
웹페이지가 처음 로딩될 때, 브라우저는 서버에서 HTML 파일을 받아와서 파싱(parsing)을 시작합니다.
이 과정에서 DOM 트리(DOM Tree) 라는 구조가 만들어지는데요.
이 트리는 JavaScript나 CSS가 HTML 요소를 조작할 수 있도록 브라우저가 내부적으로 HTML을 객체처럼 변환한 결과입니다.
이 단계의 특징은요:
- 아직 외부 리소스(CSS, 이미지 등)는 완전히 불러오지 않은 상태입니다.
- JavaScript로 이 파싱 과정을 직접 감지하거나 중단시킬 수는 없습니다.
- 하지만 HTML 구조를 깔끔하게 정리하고, 불필요한 blocking 리소스를 줄이면 전체 파싱 속도를 개선할 수 있습니다.
2. 외부 리소스 로딩: CSS와 JavaScript는 언제 불러올까?
브라우저가 HTML을 읽다가 <link>
나 <script>
같은 외부 리소스를 만나면, 각각의 리소스 종류에 따라 다른 방식으로 처리합니다.
CSS 로딩
<link>
태그를 만나면 CSS 파일을 불러오고 파싱할 때까지 렌더링을 중단합니다.- CSS는 스타일을 적용하는 데 필수이기 때문에, 안 불러오면 페이지가 망가질 수 있죠.
- 그래서 CSS는 렌더링 차단 요소(render-blocking resource) 로 분류됩니다.
JavaScript 로딩
<script>
태그는 기본적으로 HTML 파싱을 멈추고 스크립트를 먼저 불러와 실행합니다.- 이 동작을 동기적(synchronous) 이라고 하는데요, 이 때문에
DOMContentLoaded
이벤트가 느려질 수 있습니다. <script defer>
나<script async>
를 사용하면 이 지연을 줄일 수 있습니다.
이처럼 외부 리소스가 어떤 방식으로 불러와지는지에 따라 페이지 전체의 로딩 속도와 반응성이 크게 달라집니다.
3. readyState와 readystatechange: 문서 상태 확인하기
HTML 문서나 AJAX 요청이 어느 단계에 있는지 확인하려면 document.readyState
속성과 readystatechange
이벤트를 활용할 수 있습니다.
document.readyState의 값
loading
: HTML이 아직 파싱 중일 때interactive
: HTML 파싱이 끝나고 DOM 트리 생성은 완료된 상태 (이미지나 스타일시트는 불완전할 수 있음)complete
: 모든 HTML, CSS, JavaScript, 이미지까지 전부 로딩 완료
if (document.readyState === 'complete') {
// 페이지가 완전히 로딩된 상태
}
readystatechange 이벤트
이 이벤트는 readyState
값이 바뀔 때마다 발생합니다.
이를 통해 DOM 조작 타이밍을 조절할 수 있죠.
document.addEventListener('readystatechange', function () {
if (document.readyState === 'interactive') {
console.log('DOM 트리 생성 완료');
} else if (document.readyState === 'complete') {
console.log('모든 리소스 로딩 완료');
}
});
4. DOMContentLoaded: DOM이 준비됐을 때 실행되는 이벤트
DOMContentLoaded
는 HTML 파싱이 끝나고 DOM 트리가 생성됐을 때 발생하는 이벤트입니다.
이 시점에서는 이미지나 스타일시트 같은 외부 리소스는 아직 다 불러오지 않았을 수 있습니다.
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM이 준비됐습니다.');
});
예시: 이미지가 있는 페이지에서
DOMContentLoaded
이벤트는 이미지가 다 불러지기 전에 발생합니다.
function ready() {
const img = document.querySelector('#img');
console.log(`이미지 크기: ${img.offsetWidth}x${img.offsetHeight}`);
}
document.addEventListener('DOMContentLoaded', ready);
이 코드 실행 시점에는 이미지가 아직 로딩되지 않았기 때문에, 이미지 크기는 0x0
으로 출력될 수 있습니다.
5. window.onload: 모든 리소스가 다 불러졌을 때 실행되는 이벤트
window.onload
는 HTML뿐 아니라 CSS, 이미지, 폰트, 비디오 등 모든 외부 자원까지 다 불러진 다음에 발생합니다.
window.onload = function () {
console.log('페이지 로딩 완료');
console.log(`이미지 크기: ${img.offsetWidth}x${img.offsetHeight}`);
};
이 경우에는 이미지도 완전히 로딩된 상태이기 때문에, 실제 크기가 정확히 출력됩니다.
6. beforeunload 이벤트: 페이지를 떠나기 전 사용자에게 알림
beforeunload
이벤트는 사용자가 페이지를 떠나기 직전에 발생합니다.
예를 들어, 작성 중인 글을 저장하지 않고 나가려고 할 때 경고 메시지를 띄울 수 있죠.
window.onbeforeunload = function () {
return false; // 사용자에게 떠날 건지 확인하는 메시지 표시
};
현대 브라우저는 보안과 사용자 경험을 위해 사용자 정의 메시지를 무시하고, 표준화된 경고창만 보여줍니다.
너무 자주 사용하면 오히려 불편함을 줄 수 있으니, 꼭 필요한 경우에만 쓰는 게 좋습니다.
7. unload 이벤트: 페이지가 완전히 종료될 때
unload
이벤트는 페이지가 완전히 닫히거나 다른 페이지로 이동할 때 발생합니다.
이 이벤트는 사용자에게 메시지를 띄울 수 없고, 단순히 정리(clean-up) 작업에 사용됩니다.
사용 예시:
- 비동기 요청 취소
- 메모리 정리
- 웹소켓 연결 종료
localStorage
저장- 분석 데이터 전송
window.addEventListener('unload', function () {
navigator.sendBeacon('/analytics', JSON.stringify(analyticsData));
});
sendBeacon()
은 페이지가 종료되는 순간에도 데이터를 서버로 전송할 수 있어, 분석 도구에서 자주 사용됩니다.
정리하며
브라우저가 HTML 문서를 불러오고 사용자에게 보여주기까지는 다양한 단계가 있는데요.
이를 정리해보면 다음과 같습니다:
- HTML 파싱: DOM 트리 생성
- DOMContentLoaded: DOM 생성 후 발생, 외부 리소스는 아직 로딩 중일 수 있음
- load: 모든 리소스 로딩 완료 후 발생
- beforeunload: 페이지 이탈 직전 사용자에게 경고
- unload: 페이지 완전히 종료되며 정리 작업 진행
이 생명주기를 이해하고 활용하면, 사용자에게 더 빠르고 안정적인 웹 경험을 제공할 수 있습니다.
특히 DOMContentLoaded와 load 이벤트를 잘 구분하고, 외부 리소스 로딩 방식을 최적화하면 성능 차이가 크게 나타날 수 있습니다.
'Javascript' 카테고리의 다른 글
Node.js에서 .aspx 파일을 읽는 방법: 정적 HTML부터 서버 통합까지 (1) | 2025.04.12 |
---|---|
Node.js에서 Moment.js로 타임스탬프 다루기 완전 정복 (1) | 2025.04.12 |
Express.js 5.0.0 정식 출시! (1) | 2025.03.31 |
HTTP 캐싱 완전 정복: 웹 성능 향상을 위한 필수 가이드 (0) | 2025.03.29 |
대용량 파일 업로드 최적화 방법: 초보자도 쉽게 따라 하는 6가지 전략 (0) | 2025.03.24 |