웹 브라우저 렌더링 1부 - 객체 모델 생성
목차
- 들어가며
- 객체 모델이란?
- DOM (Document Object Model)
- CSSOM (CSS Object Model)
- 실제 예시
- DOM 생성 과정
- 바이트에서 문자로의 변환
- 문자에서 토큰으로의 변환
- 토큰에서 노드로의 변환
- DOM 트리 구축
- CSSOM 생성 과정
- CSS 파싱 프로세스
- CSSOM 트리 구축
- 스타일 규칙 처리
- 렌더링 프로세스 개요
- 렌더링 트리 생성
- DOM과 CSSOM의 결합
- display: none vs visibility: hidden
- 레이아웃(리플로우) 계산
- 페인트(래스터화) 단계
- 최적화 고려사항
- 주요 렌더링 경로
- 성능 영향 요소
- DevTools를 통한 모니터링
- 결론
들어가며
웹 브라우저가 어떻게 HTML, CSS, JavaScript를 처리하여 우리가 보는 웹 페이지를 만들어내는지 이해하는 것은 프론트엔드 개발자에게 매우 중요합니다. 이 시리즈의 첫 번째 글에서는 브라우저가 웹 페이지를 렌더링하는 첫 단계인 ‘객체 모델 생성’ 과정을 살펴보겠습니다.
객체 모델이란?
브라우저는 페이지를 렌더링하기 위해 두 가지 주요 객체 모델을 생성합니다:
- DOM (Document Object Model): HTML 문서의 객체 기반 표현
- CSSOM (CSS Object Model): CSS의 객체 기반 표현
실제 예시
다음과 같은 간단한 HTML 파일이 있다고 가정해보겠습니다:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html>
<head>
<title>카페 메뉴</title>
<style>
.menu-item { color: brown; }
.price { color: green; }
</style>
</head>
<body>
<h1>오늘의 메뉴</h1>
<div class="menu-item">
아메리카노 <span class="price">4,000원</span>
</div>
</body>
</html>
DOM 생성 과정
1. 바이트 → 문자
브라우저가 처음 받는 것은 바이트 스트림입니다:
3C 68 74 6D 6C 3E ...
이것이 문자로 변환됩니다:
1
<html>...
2. 문자 → 토큰
문자열은 의미 있는 토큰으로 변환됩니다:
1
2
3
4
5
6
7
8
9
10
11
12
{
type: 'StartTag',
tagName: 'html'
},
{
type: 'StartTag',
tagName: 'head'
},
{
type: 'StartTag',
tagName: 'title'
},
3. 토큰 → 노드
각 토큰은 속성과 규칙을 가진 노드 객체로 변환됩니다:
1
2
3
4
5
6
{
type: 'element',
tagName: 'div',
attributes: [{ name: 'class', value: 'menu-item' }],
children: []
}
4. 노드 → DOM
최종적으로 완성되는 DOM 트리의 구조:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Document
└── html
├── head
│ ├── title
│ │ └── "카페 메뉴"
│ └── style
│ └── ".menu-item { color: brown; } ..."
└── body
├── h1
│ └── "오늘의 메뉴"
└── div.menu-item
├── "아메리카노"
└── span.price
└── "4,000원"
CSSOM 생성 과정
위 HTML의 스타일 부분을 보면:
1
2
.menu-item { color: brown; }
.price { color: green; }
1. CSS 파싱 프로세스
CSS 바이트 스트림도 DOM과 유사한 과정을 거칩니다:
1
2E 6D 65 6E 75 2D ... → .menu-item { ... }
2. CSSOM 트리 구축
파싱된 CSS는 다음과 같은 토큰으로 변환됩니다:
1
2
3
4
5
6
7
8
9
{
type: 'selector',
value: '.menu-item'
},
{
type: 'property',
name: 'color',
value: 'brown'
}
3. 최종 CSSOM 트리
1
2
3
4
5
Rule
├── Selector: .menu-item
│ └── Declaration: color: brown
└── Selector: .price
└── Declaration: color: green
렌더링 프로세스 개요
렌더링 트리 생성
CSSOM 및 DOM 트리는 결합하여 렌더링 트리를 형성합니다. 이 렌더링 트리는 표시되는 각 요소의 레이아웃을 계산하고 픽셀을 화면에 렌더링하는 페인트 프로세스의 기초가 됩니다.
DOM과 CSSOM의 결합
렌더링 트리를 생성하기 위해 브라우저는 다음 작업을 수행합니다:
- DOM 트리의 루트에서 시작하여 표시되는 각 노드를 순회합니다
- 스크립트 태그, 메타 태그 등 표시되지 않는 노드는 생략됩니다
- CSS로 숨겨진 노드도 생략됩니다
- 각 표시 노드에 대해 적절한 CSSOM 규칙을 찾아 적용합니다
- 표시 노드를 콘텐츠 및 계산된 스타일과 함께 내보냅니다
display: none vs visibility: hidden
visibility: hidden: 요소가 보이지 않지만 레이아웃에서 공간을 차지합니다 (빈 박스로 렌더링)display: none: 요소가 렌더링 트리에서 완전히 제거되어 레이아웃에 영향을 주지 않습니다
레이아웃(리플로우) 계산
예를 들어 다음과 같은 HTML이 있다고 가정해보겠습니다:
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Critial Path: Hello world!</title>
</head>
<body>
<div style="width: 50%">
<div style="width: 50%">Hello world!</div>
</div>
</body>
</html>
이 경우 브라우저는:
- 뷰포트 크기를 확인합니다
- 첫 번째 div의 너비를 뷰포트의 50%로 계산합니다
- 두 번째 div의 너비를 부모 요소의 50%(즉, 뷰포트의 25%)로 계산합니다
페인트(래스터화) 단계
레이아웃 계산이 완료되면 브라우저는 계산된 렌더링 트리를 실제 픽셀로 변환합니다. 이 과정은 다음과 같은 특징이 있습니다:
- 요소의 모든 시각적 속성이 적용됩니다
- 레이어 합성이 이루어집니다
- 최종 화면이 사용자에게 표시됩니다
최적화 고려사항
주요 렌더링 경로
주요 렌더링 경로 최적화는 다음 단계들의 총 소요 시간을 최소화하는 것을 의미합니다:
- HTML 마크업 처리 및 DOM 트리 구축
- CSS 마크업 처리 및 CSSOM 트리 구축
- DOM과 CSSOM을 결합한 렌더링 트리 생성
- 렌더링 트리에서 레이아웃 실행
- 화면에 페인트
성능 영향 요소
렌더링 성능에 영향을 주는 주요 요소들:
- 문서의 크기와 복잡도
- 적용된 스타일의 복잡도
- 실행 중인 디바이스의 성능
DevTools를 통한 모니터링
Chrome DevTools를 사용하면 렌더링 과정을 모니터링할 수 있습니다:
- Layout 이벤트: 렌더링 트리 생성 및 위치/크기 계산을 보여줍니다
- Paint Setup 및 Paint 이벤트: 픽셀 변환 과정을 나타냅니다
- 더 자세한 내용은 따로 post를 작성할 예정입니다.
결론
객체 모델 생성과 렌더링 프로세스는 웹 브라우저의 핵심 기능입니다. DOM과 CSSOM의 생성부터 최종 렌더링까지의 과정을 이해하는 것은 효율적인 웹 애플리케이션 개발을 위해 매우 중요하다고 생각합니다.
최적의 성능을 위해서는:
- DOM과 CSSOM 구조를 단순하게 유지
- 복잡한 레이아웃 변경 최소화
- 렌더링 경로 최적화에 주의
다음 포스트에서는 이러한 개념들을 바탕으로 실제 성능 최적화 전략들을 살펴보도록 하겠습니다.