파스 트리
( DOM tree
, CSSOM tree
) 로 생성하는 과정을 의미한다.파싱
하여 DOM tree
와 CSSOM tree
를 생성하고 이들을 결합하여 Render tree
를 생성한다.파싱
하여 AST (Abstract Syntax Tree)
를 생성하고 바이트코드로 변환하여 실행한다. 이때 자바스크립트는 DOM API
를 통해 DOM
이나 CSSOM
을 변경할 수 있다. 변경된 DOM
과 CSSOM
은 다시 렌더 트리로 결합된다.Render tree
를 기반으로 HTML 요소의 레이아웃을 계산하고 브라우저 화면에 HTML 요소를 페인팅한다.후에 이 과정과 관련된 자세한 내용을 포스팅하겠다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="./style.css" />
<script src="main.js"></script>
</head>
<body>
</body>
</html>
브라우저는 동기적으로, 즉 위에서 아래 방향으로 순차적으로 HTML, CSS, 자바스크립트를 파싱하고 실행한다. 이 때, HTML을 파싱하다가 CSS와 JS를 로드하는 코드를 만나면 HTML의 파싱이 중단되었다가 CSS와 JS가 파싱된 후에 다시 HTML 파싱을 이어간다.
위의 경우에는 main.js의 파싱과 실행 이전까지는 DOM의 생성이 일시 중단된다. DOM은 HTML이 모두 파싱되고 난 후에 생성되기 때문이다. 이때 자바스크립트 코드에서 DOM API를 이용해 DOM이나 CSSOM을 변경하는 경우에는 문제가 발생할 수 있다. DOM이나 CSSOM이 이미 생성되지 않은 상태에서 조작하려고 하기 때문이다.
이러한 문제를 회피하기 위해서는 body 요소의 가장 아래에 자바스크립트를 위치시키는 것은 좋은 아이디어다. 그 이유는 다음과 같다.
해당 속성은 외부 자바스크립트 파일을 src 어트리뷰트를 통해 로드하는 경우에만 사용할 수 있다. 즉, 인라인 자바스크립트에는 사용할 수 없다.
async
와 defer
어트리뷰트를 사용하면 HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적
으로 동시에 진행된다. 하지만 자바스크립트의 실행 시점
에 차이가 있다.
HTML 파싱과 외부 자바스크립트 파일의 로드가 비동기적으로 동시에 진행된다. 단, 자바스크립트의 파싱과 실행은 자바스크립트 파일의 로드가 완료된 직후에 진행되며, 이때 HTML 파싱이 중단되고, 자바스크립트 실행이 완료되면 다시 진행된다.
순서 보장이 필요한 script 태그에서는 async 어트리뷰트를 지정하지 않아야한다. 왜냐하면 script 태그를 먼저 적던 나중에 적던 빨리 로드되는 자바스크립트부터 먼저 실행되기 때문에 순서가 보장되지 않는다.
<script async src='extern.js'></script>
async 어트리뷰트와 다른 점은 자바스크립트의 파싱과 실행이 HTML 파싱이 완료된 후, 즉 DOM 생성이 완료된 직후 (이때 DOMContentLoaded
이벤트가 발생한다.) 에 진행된다. 따라서 DOM 생성이 완료된 이후 실행되어야 할 자바스크립트에 유용하다.
<script defer src='extern.js'></script>
앞선 개념에서 DOMContentLoaded
이벤트가 잠깐 나왔다. 브라우저의 이벤트에는 DOMContentLoaded
, load
, beforeunload
, unload
가 있다.
DOMContentLoaded
load
beforeunload
unload
해당 이벤트들은 브라우저가 로드되고 언로드될 때 실행하고 싶은 작업이 있으면 유용하게 사용할 수 있다.
window.addEventListener("DOMContentLoaded", () => {
console.log("HTML 파싱이 완료되었습니다.");
});