최근에 회사에 새로 입사한 신입이랑 이야기를 하던 도중, DOM이 뭔지 모른다는 충격적인 이야기를 들었습니다. HTML이 그대로 웹 브라우저에 나타나는 것으로 생각하고 있던 것이죠. 정확하게 말하자면 DOM은 브라우저마다 다르게 나타날 수 있습니다. 그것을 통일하기 위한 표준은 존재하지만요. 그래서 이번 포스팅에서는 DOM과 브라우저가 어떻게 HTML, CSS, JS를 사용자에게 보여주는지를 아주 간략하게 설명드리고자 합니다. 간략하게 설명하려다보니 내용이 다소 부실할 수도 있겠습니다. 자세한 내용을 원하시는 분들은 직접 MDN을 찾아서 확인해보시는 것을 추천합니다.
DOM의 정의
DOM(Document Object Model)은 웹 페이지에 대한 프로그래밍 인터페이스(Programming Interface)입니다. 네, API요. 마크업(HTML, XML)으로 짜여진 구조와 스타일을 읽고, 조작할 수 있도록 만들어진 API라고 이해하시면 좋겠습니다. 구조화된 nodes와 property, method를 가지고 있는 Object이기 때문에 Document Object Model이라고 불립니다.
Javascript는 이러한 DOM을 통해서 새로운 HTML요소나 속성을 추가, 변경, 제거할 수 있게 됩니다. 중요한 것은 DOM은 HTML과 동일하지 않다는 것을 이해하는 것입니다. DOM의 구조는 Node tree로 표현됩니다. 아래 예시를 보시면 <html>과 <head>, <body>로 구성된 아주 간단한 HTML임을 알 수 있습니다.
이것을 Node tree로 표현하면 아래 이미지와 같이 나타납니다.
이런 구조만 보면 마치 HTML과 DOM이 동일한 것처럼 보일 수도 있겠습니다. 하지만 다릅니다. 아래 이미지를 보시면, HTML에 반드시 포함되어야 할 <head>와 <body> 태그가 누락된 것을 볼 수 있습니다.
하지만 브라우저의 DOM tree에는 아래와 같이 교정되어서 나타납니다.
이것만 보더라도 HTML과 DOM은 완전히 동일하지 않다는 것의 증거로는 충분할 것 같습니다. 물론 Javascript를 통해서 DOM을 직접 수정하는 경우도 그 증거 중에 하나가 될 수 있겠네요. 브라우저 상에서 Javascript를 수정한다고 해서 HTML의 내용이 변경되던가요?
웹 페이지 렌더링
웹 페이지는 기본적으로 하나의 문서(Document)입니다. 이 문서는 웹 브라우저를 통해 내용이 해석되어 화면에 나타나게 됩니다. 웹 브라우저가 해석하는 일련의 과정을 중요 렌더링 경로(Critical rendering path; CRP)라고 부르는데요, DOM, CSSOM, Render tree, Layout을 포함하고 있습니다.
MDN과 Google Developers에 따르면 CRP 과정은 5단계로 이루어집니다.
- DOM tree 구성
- CSSOM tree 구성
- Render tree 구성
- Layout 생성
- Paint
DOM tree 구성
DOM tree는 HTML을 통해서 브라우저가 구성한다고 말씀드렸습니다. 하지만 우리의 웹 페이지는 HTML로만 구성되지 않았죠? 보통은 CSS나 JS같은 resource를 포함하고 있을 겁니다.
CSSOM tree 구성
HTML이 DOM으로 구성되듯이, CSS는 CSSOM(CSS Object Model)으로 구성됩니다. 이것은 DOM과는 다르게 "렌더링 차단"을 유발하는 리소스입니다. 즉, 브라우저는 모든 CSS를 처리할 때까지 Page를 사용자에게 보여주지 않습니다. CSS의 C는 Cascading이라는 의미인데요, CSS의 아래쪽에 정의된 스타일이 이전에 정의된 스타일을 덮어쓸 가능성이 있습니다. 그래서 연속적이라는 의미의 Cascading이라는 단어가 사용된 것이죠. 따라서 CSSOM tree가 모두 구성되기 전에는 브라우저가 렌더링을 차단합니다.
Render tree 구성
Render tree는 DOM과 CSSOM이 결합되면서 만들어집니다. Render tree를 구성하기 위해서 브라우저는 DOM tree의 모든 노드를 확인하고, 어떤 CSS를 첨부할지 결정합니다. Render tree에서는 오직 보여지는 요소만이 포함됩니다. 아까 DOM과 HTML이 다르다는 것을 설명드렸는데요, 만약 HTML에서 display: none; 을 지정한 요소가 있다면 이것은 DOM tree에는 포함되지만 Render tree에는 포함되지 않습니다. 여기서 참고해야할 것은 visibility: hidden;은 Render tree에 포함된다는 점이겠네요.
Layout 생성 & Paint
이렇게 Render tree가 구성되고 나면 레이아웃이 가능해집니다. 레이아웃은 요소들이 페이지에서 배치되는 위치나 방법, 각각의 너비와 높이 등을 결정합니다. 이 프로세스에서는 기기의 viewport에 대해서 모든 상대적인 측정값을 절대적인 px로 변환해줍니다. 그리고 이것들을 화면의 실제 pixel로 변환하는데, 이것을 Paint라고 합니다.