📑 목차
DOM과 CSSOM은 언제 어떻게 결합될까요
웹 페이지가 우리 눈앞에 멋진 모습으로 나타나기까지는 브라우저 내부에서 복잡하고 정교한 과정들이 숨어 있습니다. 그중에서도 핵심적인 두 가지 요소가 바로 'DOM'과 'CSSOM'입니다. 이 둘은 마치 건축물의 뼈대와 인테리어 디자인 도면처럼 각각 독립적으로 존재하다가, 특정 시점에 결합하여 우리가 보는 웹 페이지의 최종 모습을 만들어냅니다. 오늘은 이 DOM과 CSSOM이 언제, 그리고 어떻게 만나 시각적인 결과물을 만들어내는지에 대해 쉽고 자세하게 알아보겠습니다.
이 과정을 이해하는 것은 단순히 웹 페이지가 어떻게 작동하는지 아는 것을 넘어, 웹 성능을 최적화하고 사용자 경험을 개선하는 데 필수적인 지식입니다. 웹 개발자뿐만 아니라 웹 서비스에 관심 있는 일반 독자분들도 이 글을 통해 웹 페이지 로딩의 비밀을 파헤치고, 더 빠르고 효율적인 웹 환경을 만드는 데 기여할 수 있는 통찰력을 얻으시길 바랍니다.
DOM과 CSSOM의 기본 개념 이해
먼저 DOM과 CSSOM이 각각 무엇인지, 그리고 어떤 역할을 하는지 간단히 짚고 넘어가겠습니다.
DOM이란 무엇인가요
DOM은 'Document Object Model'의 약자로, 브라우저가 HTML 문서를 이해하고 조작하기 위해 사용하는 모델입니다. 우리가 작성한 HTML 코드는 텍스트 형태이지만, 브라우저는 이 텍스트를 파싱(분석)하여 컴퓨터가 이해할 수 있는 트리(Tree) 구조로 변환합니다. 이 트리 구조를 DOM 트리라고 부릅니다.
- 각 HTML 태그(예: <div>, <p>, <img>)는 DOM 트리의 '노드(Node)'가 됩니다.
- 이 노드들은 부모 자식 관계를 가지며 계층적으로 연결됩니다.
- 자바스크립트는 이 DOM 트리에 접근하여 HTML 요소의 내용을 변경하거나, 새로운 요소를 추가하거나, 기존 요소를 삭제하는 등 웹 페이지의 구조와 콘텐츠를 동적으로 조작할 수 있습니다.
DOM은 웹 페이지의 '뼈대'이자 '콘텐츠'를 담당한다고 생각하시면 됩니다.
CSSOM이란 무엇인가요
CSSOM은 'CSS Object Model'의 약자로, 브라우저가 CSS(Cascading Style Sheets) 코드를 이해하고 조작하기 위해 사용하는 모델입니다. HTML과 마찬가지로 브라우저는 CSS 파일을 파싱하여 CSSOM 트리 구조를 만듭니다.
- CSSOM 트리는 각 CSS 선택자(예: `body`, `#id`, `.class`)에 적용되는 스타일 규칙들을 계층적으로 구성합니다.
- 부모 요소의 스타일이 자식 요소에 상속되는 방식, 여러 규칙이 충돌할 때 어떤 규칙이 최종적으로 적용되는지(CSS의 '캐스케이딩' 원리) 등이 이 CSSOM 트리에 반영됩니다.
- CSSOM은 웹 페이지의 '스타일'이자 '디자인'을 담당합니다. 즉, 뼈대 위에 어떤 색깔을 칠하고, 어떤 모양으로 꾸밀지를 결정하는 역할을 합니다.
DOM과 CSSOM의 결합 과정 렌더링 트리 구축
DOM은 콘텐츠의 구조를, CSSOM은 스타일을 정의합니다. 이 둘이 각각 독립적으로 생성된 후, 브라우저는 이들을 결합하여 실제로 화면에 무엇을 어떻게 그릴지를 결정하는 중요한 단계를 거칩니다. 이 과정을 '렌더링 트리(Render Tree)' 구축이라고 합니다.
1 HTML 파싱과 DOM 생성
브라우저가 웹 페이지를 로드하기 시작하면, 가장 먼저 HTML 파일을 읽어 들여 파싱합니다. 이 과정을 통해 DOM 트리가 만들어집니다. HTML 코드를 위에서 아래로 읽어 내려가면서, 각 태그에 해당하는 DOM 노드를 생성하고 계층적으로 연결합니다.
2 CSS 파싱과 CSSOM 생성
HTML 파싱 도중 <link rel="stylesheet"> 태그나 <style> 태그를 만나면, 브라우저는 CSS 파일을 다운로드하거나 <style> 태그 안의 CSS 코드를 파싱하여 CSSOM 트리를 만듭니다. CSSOM 트리는 모든 CSS 규칙과 그 우선순위를 포함하게 됩니다.
3 스타일 계산과 렌더링 트리 구축
DOM 트리와 CSSOM 트리가 모두 준비되면, 브라우저는 이 둘을 결합하기 시작합니다. 이 과정은 다음과 같은 단계로 진행됩니다.
-
- 스타일 계산 (Style Calculation): 브라우저는 DOM 트리의 가장 상위 노드부터 시작하여 각 노드에 어떤 CSS 규칙이 적용되어야 하는지 CSSOM 트리를 참조하여 계산합니다. 이 단계에서 상속, 캐스케이딩, 우선순위 등의 모든 CSS 규칙이 적용되어 각 DOM 노드의 최종 스타일이 결정됩니다.
-
- 렌더링 트리 생성 (Render Tree Construction): 스타일 계산이 완료되면, 브라우저는 화면에 실제로 그려질 요소들만 모아 새로운 트리인 '렌더링 트리'를 만듭니다.
- 렌더링 트리는 DOM 트리의 모든 노드를 포함하지 않습니다. 예를 들어, `display: none` 속성이 적용된 요소는 화면에 표시되지 않으므로 렌더링 트리에서 제외됩니다.
- 렌더링 트리의 각 노드(렌더 객체 또는 프레임)는 해당 DOM 요소의 콘텐츠뿐만 아니라, 계산된 최종 스타일 정보(색상, 크기, 폰트, 여백 등)를 모두 포함합니다.
- 렌더링 트리 생성 (Render Tree Construction): 스타일 계산이 완료되면, 브라우저는 화면에 실제로 그려질 요소들만 모아 새로운 트리인 '렌더링 트리'를 만듭니다.
즉, DOM과 CSSOM은 '렌더링 트리'를 만드는 과정에서 비로소 결합됩니다. 렌더링 트리는 "이 요소는 어떤 내용으로, 어떤 스타일을 가지고, 어디에 표시될 것인가?"에 대한 모든 정보를 담고 있는 최종적인 청사진이라고 볼 수 있습니다.
4 레이아웃 계산 Reflow
렌더링 트리가 구축되면, 브라우저는 각 렌더 객체의 정확한 위치와 크기를 계산합니다. 이 과정을 '레이아웃(Layout)' 또는 '리플로우(Reflow)'라고 합니다. 이 단계에서 뷰포트 크기, 요소의 여백, 패딩, 테두리, 글자 크기 등 모든 시각적 속성이 고려되어 화면에서의 실제 좌표와 크기가 결정됩니다.
5 페인팅 Repaint
레이아웃 계산이 끝나면, 브라우저는 계산된 위치와 크기 정보를 바탕으로 픽셀을 화면에 그립니다. 이 과정을 '페인팅(Painting)' 또는 '리페인트(Repaint)'라고 합니다. 배경색, 텍스트, 이미지, 테두리 등 모든 시각적 요소가 이 단계에서 화면에 나타나게 됩니다.
언제 DOM과 CSSOM의 결합이 일어나는가
DOM과 CSSOM의 결합, 즉 렌더링 트리 구축은 기본적으로 HTML 문서의 초기 로드 시점에 발생합니다. 하지만 단순히 한 번만 일어나는 과정이 아닙니다.
- 초기 페이지 로드 시: HTML과 CSS 파일이 모두 파싱되어 DOM과 CSSOM이 완성되면 즉시 렌더링 트리 구축이 시작됩니다. 이때, 브라우저는 CSSOM이 완전히 준비되기 전까지는 렌더링 트리를 만들 수 없습니다. 이것이 바로 CSS 파일이 렌더링 차단 리소스(render-blocking resource)로 간주되는 이유입니다.
- DOM 또는 CSSOM이 변경될 때: 자바스크립트를 사용하여 DOM을 조작(예: 새로운 요소 추가, 기존 요소 삭제, 텍스트 변경)하거나 CSSOM을 조작(예: 요소의 스타일 변경, 클래스 추가/제거)하면, 브라우저는 변경된 부분에 대해 DOM과 CSSOM을 다시 결합하고 렌더링 트리를 재구축해야 할 수 있습니다. 이러한 변경이 발생하면 레이아웃(리플로우)과 페인팅(리페인트) 과정이 다시 발생하며, 이는 웹 페이지의 성능에 직접적인 영향을 미칩니다.
- 브라우저 창 크기 변경 시: 브라우저 창의 크기를 변경하면 뷰포트의 크기가 달라지므로, 모든 요소의 레이아웃이 다시 계산되어야 합니다. 이 역시 렌더링 트리를 기반으로 한 리플로우와 리페인트를 유발합니다.
웹 성능 최적화를 위한 실생활 활용 팁
DOM과 CSSOM의 결합 과정을 이해하면 웹 페이지의 로딩 속도를 향상시키고 부드러운 사용자 경험을 제공하기 위한 다양한 최적화 전략을 세울 수 있습니다.
CSS 파일을 HTML 문서 상단에 배치하세요
CSSOM은 렌더링 트리를 구축하는 데 필수적이므로, CSS 파일이 빨리 로드되고 파싱되어야 합니다. <link rel="stylesheet"> 태그를 <head> 섹션 안에 배치하여 브라우저가 가능한 한 빨리 CSSOM을 만들 수 있도록 하세요. 이렇게 하면 브라우저가 스타일 없는 콘텐츠(FOUC, Flash Of Unstyled Content)를 보여주는 것을 방지하고, 렌더링을 빠르게 시작할 수 있습니다.
JavaScript 파일을 HTML 문서 하단에 배치하거나 defer async 속성을 사용하세요
기본적으로 자바스크립트는 파싱을 차단합니다. 즉, 브라우저가 <script> 태그를 만나면 HTML 파싱을 멈추고 스크립트를 다운로드하여 실행한 후에야 다시 HTML 파싱을 재개합니다. 이는 DOM 생성을 지연시키고, 결과적으로 렌더링 트리 구축을 늦출 수 있습니다.
- <body> 태그의 닫는 태그 직전에 자바스크립트를 배치하여 DOM 생성을 방해하지 않도록 합니다.
- <script src="script.js" defer></script> 속성을 사용하면 HTML 파싱이 완료된 후에 스크립트가 실행됩니다.
- <script src="script.js" async></script> 속성을 사용하면 스크립트가 비동기적으로 다운로드 및 실행되며, HTML 파싱을 차단하지 않습니다. 단, 스크립트 간의 실행 순서가 중요하지 않을 때 사용해야 합니다.
불필요한 CSS를 제거하세요
사용하지 않는 CSS 규칙이 많으면 CSSOM 트리가 불필요하게 커지고, 스타일 계산 시간이 길어집니다. 웹 페이지에서 실제로 사용되는 CSS만 포함하도록 코드를 정리하고 최적화하세요. (예: PurgeCSS와 같은 도구 활용).
복잡한 CSS 선택자를 피하세요
브라우저가 복잡한 선택자(예: `div > div > ul > li:nth-child(odd) > a`)에 해당하는 요소를 찾아 스타일을 적용하는 데 더 많은 시간이 소요됩니다. 간단하고 효율적인 선택자(예: `.menu-item-link`)를 사용하는 것이 스타일 계산 비용을 줄이는 데 도움이 됩니다.
레이아웃 변경 Reflow를 최소화하세요
자바스크립트나 CSS 변경으로 인해 요소의 크기나 위치가 변경되면 브라우저는 레이아웃을 다시 계산(리플로우)하고 화면을 다시 그리는(리페인트) 작업을 수행합니다. 리플로우는 비용이 많이 드는 작업이므로, 애니메이션이나 동적인 UI를 구현할 때는 `transform`, `opacity`와 같이 레이아웃에 영향을 주지 않는 CSS 속성을 사용하는 것이 좋습니다.
미디어 쿼리를 활용하여 필요한 CSS만 로드하세요
반응형 웹 디자인에서 미디어 쿼리를 사용하여 특정 화면 크기나 장치에만 필요한 CSS를 로드할 수 있습니다. 이는 초기 CSSOM의 크기를 줄여 렌더링 성능을 향상시키는 데 기여합니다.
흔한 오해와 사실 관계
DOM과 CSSOM, 그리고 렌더링 과정에 대해 흔히 오해하는 몇 가지 사실들을 바로잡아 보겠습니다.
오해 CSS는 렌더링을 차단하지 않는다
사실 CSS는 렌더링을 차단합니다. 브라우저는 CSSOM이 완전히 완성되기 전까지는 렌더링 트리를 구축할 수 없습니다. 이는 사용자가 스타일이 적용되지 않은 콘텐츠를 보는 것을 방지하기 위한 것으로, CSSOM이 준비될 때까지 브라우저는 렌더링을 멈추고 기다립니다.
오해 자바스크립트는 항상 비동기적으로 실행된다
사실 기본적으로 자바스크립트는 파싱을 차단합니다. 즉, <script> 태그를 만나면 HTML 파싱을 일시 중지하고 스크립트가 다운로드 및 실행될 때까지 기다립니다. `async`나 `defer` 속성을 명시적으로 사용해야 비동기적으로 실행됩니다.
오해 DOM과 CSSOM은 한 번만 만들어진다
사실 DOM과 CSSOM은 초기 페이지 로드 시 생성되지만, JavaScript를 통해 DOM을 조작하거나 새로운 CSS를 동적으로 로드하면 이들이 부분적으로 또는 전체적으로 다시 계산될 수 있습니다. 이러한 변경은 렌더링 트리의 재구축과 리플로우/리페인트를 유발하여 성능 저하의 원인이 될 수 있습니다.
자주 묻는 질문과 답변
질문 DOM과 CSSOM은 왜 따로 만들어지나요
답변 HTML과 CSS는 서로 다른 목적을 가지고 있고, 브라우저는 각 언어를 효율적으로 파싱하고 처리하기 위해 별도의 객체 모델을 만듭니다. HTML은 콘텐츠와 구조를, CSS는 스타일과 표현을 담당합니다. 이들을 분리하여 처리함으로써 유연성과 확장성을 확보할 수 있으며, 개발자가 특정 부분만 독립적으로 조작할 수 있게 됩니다.
질문 렌더링 트리는 DOM과 완전히 똑같은가요
답변 아닙니다. 렌더링 트리는 DOM 트리를 기반으로 하지만, 화면에 실제로 그려지는 요소들만 포함합니다. 예를 들어, `display: none` 속성이 적용된 요소는 DOM 트리에는 존재하지만 렌더링 트리에는 포함되지 않습니다. 또한, 렌더링 트리는 각 요소에 적용된 최종 스타일 정보(색상, 크기, 위치 등)를 모두 포함하고 있어 DOM 트리보다 더 많은 시각적 정보를 가지고 있습니다.
질문 자바스크립트가 CSSOM에 영향을 줄 수 있나요
답변 네, 자바스크립트는 `element.style.propertyName`을 통해 직접 CSS 속성을 변경하거나, `element.classList.add()` 또는 `element.classList.remove()` 등을 통해 클래스를 추가/제거하여 CSSOM에 영향을 줄 수 있습니다. 이러한 변경은 브라우저가 CSSOM을 업데이트하고, 렌더링 트리의 재구축 및 리플로우/리페인트를 유발할 수 있습니다.
질문 개발자 도구로 DOM과 CSSOM 결합 과정을 볼 수 있나요
답변 네, 크롬 개발자 도구(Chrome DevTools)의 'Performance' 탭에서 웹 페이지 로딩 과정을 녹화하면 'Layout', 'Recalculate Style', 'Paint' 등의 이벤트를 시각적으로 확인할 수 있습니다. 'Elements' 탭에서는 특정 요소에 적용된 최종 스타일(`Computed` 탭)을 확인하여 CSSOM이 어떻게 적용되었는지 파악할 수 있습니다.
비용 효율적인 활용 방법
웹 성능 최적화는 단순히 기술적인 문제뿐만 아니라, 사용자 경험과 직결되며 비즈니스 성과에도 영향을 미칩니다. 다음은 비용 효율적으로 DOM과 CSSOM 결합 과정을 최적화하는 몇 가지 방법입니다.
CDN 콘텐츠 전송 네트워크 활용
CSS, JavaScript 파일과 같은 정적 리소스들을 CDN(콘텐츠 전송 네트워크)에 호스팅하면 사용자에게 물리적으로 가장 가까운 서버에서 파일을 전송하게 됩니다. 이는 네트워크 지연 시간을 줄여 파일 다운로드 속도를 높이고, 결과적으로 DOM과 CSSOM 생성을 가속화하여 렌더링 시작 시간을 단축하는 데 기여합니다. 별도의 서버 구축 없이 저렴한 비용으로 강력한 성능 향상을 얻을 수 있습니다.
브라우저 캐싱 전략
HTTP 헤더의 `Cache-Control` 속성을 적절히 설정하여 CSS, JavaScript 파일을 브라우저에 캐싱하도록 지시할 수 있습니다. 사용자가 웹 페이지를 재방문하거나 다른 페이지로 이동할 때, 캐싱된 파일은 다시 다운로드할 필요 없이 즉시 사용되므로, 네트워크 요청을 줄이고 렌더링 과정을 빠르게 시작할 수 있습니다. 이는 서버 부하를 줄이고 사용자 경험을 크게 향상시키는 매우 비용 효율적인 방법입니다.
Critical CSS 인라인화
페이지의 초기 화면(Above-the-fold content)을 렌더링하는 데 필요한 최소한의 CSS(Critical CSS)만을 HTML 문서 내에 <style> 태그로 직접 인라인하는 전략입니다. 이렇게 하면 외부 CSS 파일의 다운로드를 기다리지 않고도 브라우저가 즉시 CSSOM의 핵심 부분을 구축하고 초기 렌더링을 시작할 수 있습니다. 나머지 CSS는 비동기적으로 로드하여 전체 렌더링을 방해하지 않도록 합니다. 이 방법은 초기 로딩 속도, 특히 First Contentful Paint(FCP)를 크게 개선하는 데 효과적입니다.
이미지 및 미디어 최적화
직접적으로 DOM/CSSOM 결합 과정과 관련이 적어 보일 수 있지만, 최적화되지 않은 이미지나 비디오는 네트워크 대역폭을 크게 소모하여 HTML, CSS, JavaScript와 같은 중요한 리소스의 다운로드를 지연시킬 수 있습니다. 이미지 압축, 적절한 포맷(WebP 등) 사용, 지연 로딩(Lazy Loading) 구현 등을 통해 미디어 리소스를 최적화하면 네트워크 트래픽을 줄이고 브라우저가 핵심 렌더링 작업을 더 빠르게 수행할 수 있도록 도와줍니다. 이는 간접적으로 DOM 및 CSSOM 처리 속도 향상에 기여합니다.
번들러 및 미니파이어 활용
Webpack, Parcel과 같은 모듈 번들러와 UglifyJS, CSSNano와 같은 미니파이어 도구를 사용하여 CSS와 JavaScript 파일을 압축하고 불필요한 공백이나 주석을 제거할 수 있습니다. 이렇게 최적화된 파일은 크기가 작아져 다운로드 시간이 단축되고, 브라우저가 파싱하는 데 걸리는 시간도 줄어듭니다. 이는 DOM과 CSSOM 생성 시간을 단축시켜 전체적인 렌더링 성능을 향상시키는 기본적이면서도 중요한 방법입니다.
'생활 정보' 카테고리의 다른 글
| CSS 변경 하나가 페이지 전체를 다시 그리게 만드는 이유 (0) | 2026.01.03 |
|---|---|
| Reflow와 Repaint의 차이를 CSS 관점에서 정확히 설명해보자 (0) | 2026.01.03 |
| 브라우저는 CSS를 어떤 순서로 처리할까? 렌더링 파이프라인 정리 (0) | 2026.01.03 |
| Layout Thrashing을 유발하는 CSS 패턴과 피하는 방법 (0) | 2025.12.18 |
| CSS 속성별 GPU 가속 여부 정리 (transform, filter, opacity 등) (0) | 2025.12.18 |