Unisquads
로그인
홈
이용약관·개인정보처리방침·콘텐츠정책·© 2026 Unisquads
이용약관·개인정보처리방침·콘텐츠정책
© 2026 Unisquads. All rights reserved.

브라우저 렌더링 파싱 및 렌더 트리 (r1)

이 문서의 과거 버전 (r1)을 보고 있습니다. 수정일: 2026.02.13 22:16

브라우저 렌더링 파싱 및 렌더 트리

주제

브라우저 렌더링 파싱 및 렌더 트리

분류

웹 개발, 프론트엔드

관련 기술

HTML, CSS, DOM, CSSOM

주요 개념

파싱, 렌더링, Critical Rendering Path

목적

웹 페이지의 시각적 표현 생성

상세 정보

파싱 단계

HTML 파싱 → DOM 트리 생성, CSS 파싱 → CSSOM 트리 생성

렌더 트리 생성

DOM 트리와 CSSOM 트리를 결합하여 생성

레이아웃(리플로우)

렌더 트리의 각 노드에 대한 정확한 위치와 크기 계산

페인팅

레이아웃 단계에서 계산된 정보를 픽셀로 변환하여 화면에 그리기

최적화 요소

CSS 배치 최적화, 자바스크립트 실행 시점 관리, 리소스 우선순위 지정

주요 브라우저 엔진

WebKit, Blink, Gecko

성능 영향

First Contentful Paint, Largest Contentful Paint 등 웹 성능 지표에 직접적 영향

1. 개요

브라우저 렌더링은 웹 브라우저가 HTML, CSS, 자바스크립트 등의 웹 리소스를 다운로드받아, 이를 해석하고 화면에 시각적인 픽셀로 표시하는 일련의 과정을 말한다. 이 과정은 사용자가 웹 페이지에 접속했을 때부터 화면에 콘텐츠가 그려질 때까지 내부적으로 수행되는 핵심 작업이다.

렌더링의 주요 목표는 문서 객체 모델(DOM)과 CSS 객체 모델(CSSOM)을 결합한 렌더 트리를 구성하고, 이를 기반으로 각 요소의 정확한 위치와 크기를 계산(레이아웃)한 후, 최종적으로 픽셀을 채워 그리는(페인팅) 것이다. 이 과정은 일반적으로 다음과 같은 순차적 단계를 거친다.

1. 파싱: HTML 파서가 HTML 문서를 해석하여 DOM 트리를 구축한다. 동시에 CSS 파서가 모든 CSS 스타일시트를 해석하여 CSSOM 트리를 구축한다.

2. 렌더 트리 생성: DOM 트리와 CSSOM 트리를 결합하여 화면에 표시될 모든 시각적 요소와 그 스타일 정보를 포함하는 렌더 트리를 생성한다.

3. 레이아웃(리플로우): 렌더 트리의 각 노드에 대해 화면 상의 정확한 위치와 크기를 픽셀 단위로 계산한다.

4. 페인팅: 계산된 기하학적 정보와 스타일을 바탕으로 각 노드를 실제 픽셀로 채워 그린다. 이 단계는 때때로 합성(Compositing)이라는 추가 단계를 포함하기도 한다.

이 과정은 정적이지 않으며, 사용자 상호작용이나 스크립트 실행에 의해 DOM이나 CSSOM이 변경되면 필요한 부분만 다시 계산하는 리플로우와 리페인트가 발생한다. 따라서 렌더링 성능 최적화는 불필요한 리플로우와 리페인트를 최소화하는 데 초점을 맞춘다.

2. 브라우저 렌더링 엔진의 역할

브라우저 렌더링 엔진은 HTML, CSS, 자바스크립트와 같은 웹 리소스를 받아 사용자가 볼 수 있는 시각적인 웹 페이지로 변환하는 핵심 소프트웨어 컴포넌트이다. 주요 브라우저마다 자체 엔진을 보유하고 있으며, 대표적으로 크롬과 엣지의 블링크(Blink), 사파리의 웹킷(WebKit), 파이어폭스의 게코(Gecko) 엔진이 있다.

렌더링 엔진의 주요 역할은 파싱과 렌더 트리 구축, 레이아웃 계산, 페인팅 실행이라는 일련의 과정을 통해 화면을 그리는 것이다. 이 과정은 일반적으로 다음과 같은 순서로 진행된다.

1. HTML 파서가 HTML 문서를 분석하여 DOM 트리를 구축한다.

2. CSS 파서가 CSS 규칙을 분석하여 CSSOM 트리를 구축한다.

3. DOM 트리와 CSSOM 트리를 결합하여 렌더 트리를 생성한다.

4. 렌더 트리의 각 노드에 대해 화면에서의 정확한 위치와 크기를 계산하는 레이아웃(리플로우)을 수행한다.

5. 계산된 기하학적 정보를 바탕으로 실제 픽셀을 화면에 그리는 페인팅(래스터화)을 수행한다.

이러한 렌더링 과정은 점진적으로 처리된다. 엔진은 모든 HTML을 파싱할 때까지 기다리지 않고, 일부 내용이 파싱되면 즉시 렌더 트리를 구축하고 레이아웃을 시작한다. 이는 네트워크로부터 나머지 내용이 전송되는 동시에 화면 일부를 표시할 수 있도록 하여 사용자 경험을 향상시킨다.

3. HTML 파싱과 DOM 트리 구축

HTML 문서는 문자열의 형태로 네트워크를 통해 전달된다. 브라우저의 렌더링 엔진은 이 문자열을 해석하여 웹 페이지의 구조를 나타내는 DOM 트리를 구축한다. 이 과정을 파싱이라고 한다.

파싱은 크게 두 단계로 나눌 수 있다. 첫 번째는 어휘 분석 또는 토큰화 단계이다. 렌더링 엔진은 HTML 문자열을 구성하는 문자들을 읽어 <html>, <body>, "class"와 같은 의미 있는 최소 단위인 토큰으로 분해한다. 두 번째는 구문 분석 단계로, 생성된 토큰들을 HTML 문법 규칙에 따라 계층적인 트리 구조, 즉 DOM 트리로 변환한다. 이 트리의 각 노드는 문서의 요소, 속성, 텍스트 콘텐츠 등을 나타낸다.

파싱 과정 중 <script> 태그를 만나면 엔진은 기본적으로 HTML 파싱을 중단하고 JavaScript 코드를 다운로드하고 실행한다[1]. 이로 인해 페이지 렌더링이 지연될 수 있다. <link> 태그를 통해 외부 CSS 파일을 로드하는 경우, CSSOM이 완성되기 전까지 렌더 트리 생성이 차단된다. 그러나 CSS 파싱은 기본적으로 HTML 파싱과 병행될 수 있다.

최종적으로 생성된 DOM 트리는 문서 객체 모델의 인터페이스를 제공한다. 이는 JavaScript가 동적으로 문서의 구조, 스타일, 콘텐츠에 접근하고 조작할 수 있는 기반이 된다.

3.1. 토큰화와 트리 생성

HTML 문서는 문자열 형태로 브라우저에 전달된다. 렌더링 엔진은 이 문자열을 해석하여 DOM 트리를 구축하는데, 이 과정은 크게 토큰화와 트리 생성 두 단계로 나뉜다.

첫 번째 단계인 토큰화는 입력 문자열을 의미 있는 최소 단위인 토큰으로 분해하는 과정이다. 렌더링 엔진의 HTML 파서는 문서를 처음부터 순차적으로 읽으며, 여는 태그(<div>), 닫는 태그(</div>), 속성 이름과 값, 텍스트 내용 등을 식별하여 토큰으로 변환한다. 이 과정은 어휘 분석에 해당하며, 파서는 HTML 명세에 정의된 규칙에 따라 태그의 상태를 관리한다.

토큰화가 진행되는 동시에 두 번째 단계인 트리 생성이 시작된다. 파서는 생성된 토큰들을 순서대로 처리하여 문서의 계층 구조를 반영하는 DOM 트리를 구성한다. 트리는 Document 객체를 루트로 하며, 각 토큰은 해당하는 노드로 변환되어 트리에 추가된다. 예를 들어, <html> 토큰은 HTML 요소 노드가 되고, 그 안의 텍스트는 텍스트 노드가 된다. 파서는 여는 태그 토큰을 만나면 새로운 요소 노드를 생성하고 트리의 현재 위치에 추가하며, 닫는 태그 토큰을 만나면 트리에서 한 단계 위로 이동한다.

단계

입력

출력

주요 동작

토큰화

HTML 문자열

토큰 시퀀스

문자열 스캔, 태그/속성/텍스트 식별

트리 생성

토큰 시퀀스

DOM 트리

노드 생성, 부모-자식 관계 구성, 트리 구조 완성

이 과정은 파서가 문서의 끝에 도달할 때까지 반복되며, 최종적으로 메모리 상에 문서의 전체 구조를 표현하는 DOM 트리가 완성된다. 파싱 중 자바스크립트 코드를 실행하는 <script> 태그를 만나면, 일반적으로 파싱이 일시 중단되고 스크립트가 실행된 후에 파싱이 재개된다[2].

3.2. 파싱 중 스크립트와 스타일시트 처리

HTML 파서는 일반적으로 토큰화와 트리 생성 과정을 순차적으로 진행하지만, <script> 태그나 <link> 태그(특히 rel="stylesheet"인 경우)와 같은 외부 리소스를 만나면 파싱 동작이 차단될 수 있다. 이는 브라우저가 문서의 구조와 스타일을 정확하게 해석하고 실행하기 위한 필수적인 동작이다.

자바스크립트는 document.write()와 같은 메서드를 통해 DOM을 동적으로 수정할 수 있기 때문에, 파서는 <script> 태그를 만나면 즉시 파싱을 중지하고 스크립트를 다운로드(외부 스크립트인 경우)하고 실행한다. 스크립트 실행이 완료된 후에야 나머지 HTML 파싱을 재개한다. async나 defer 속성을 사용하면 이 차단 동작을 최적화할 수 있다[3]. 반면, CSS 스타일시트는 렌더링을 차단하는 자원이다. 파서는 <link rel="stylesheet">를 만나면 해당 스타일시트의 다운로드와 파싱이 완료될 때까지 이후의 렌더 트리 구축을 보류한다. 이는 스타일이 적용되지 않은 상태로 요소가 렌더링되는 것을 방지하기 위함이다.

이러한 차단 동작은 파싱과 렌더링의 순서를 보장하지만, 성능에 영향을 미칠 수 있다. 주요 최적화 기법은 다음과 같다.

리소스 유형

파싱 차단 여부

실행/적용 시점

최적화 방법

동기 <script>

HTML 파싱 중단

즉시 다운로드 및 실행

스크립트를 문서 하단에 배치, async/defer 속성 사용

외부 CSS

렌더 트리 구축 중단

다운로드 및 파싱 완료 후

미디어 쿼리 활용, 중요 CSS 인라인 처리, 불필요한 스타일 제거

따라서, 스크립트와 스타일시트의 로딩 순서와 위치를 신중히 설계하는 것이 초기 렌더링 성능을 높이는 핵심이다.

4. CSS 파싱과 CSSOM 트리 구축

CSS 코드는 브라우저의 렌더링 엔진이 HTML 파싱과 병행하여 처리한다. HTML 파서가 DOM 트리를 구축하는 동안, 링크된 외부 CSS 파일을 발견하거나 문서 내 <style> 블록을 만나면, 해당 CSS 리소스를 로드하고 파싱 프로세스를 시작한다.

CSS 파싱은 CSS 문법 규칙에 따라 토큰화와 구문 분석을 거쳐 CSSOM 트리를 생성한다. CSSOM은 CSS Object Model의 약자로, 모든 CSS 규칙과 스타일 정보를 포함하는 트리 구조의 데이터 모델이다. 이 트리는 계단식과 상속 규칙을 적용하여 최종적으로 각 요소에 적용될 계산된 스타일을 결정하는 데 사용된다. CSS 파싱은 기본적으로 탑다운 방식으로 진행되며, 선택자의 특이성과 규칙의 순서에 따라 스타일이 결정된다.

CSSOM 트리의 구조는 DOM 트리와 유사하지만, 스타일 정보만을 담고 있다는 점이 다르다. 또한, CSS 파싱은 렌더 차단 리소스로 간주된다. 브라우저는 CSSOM이 완전히 구축되기 전까지 렌더 트리 생성을 차단하기 때문에, CSS 파일의 로드와 파싱 지연은 페이지 렌더링 시작 시점에 직접적인 영향을 미친다. 이는 사용자가 빈 페이지를 보는 시간을 증가시킬 수 있다.

특성

설명

트리 유형

규칙 기반 트리 (Rule-based Tree)

주요 내용

선택자와 선언 블록(속성-값 쌍)

생성 목적

최종 렌더링 스타일 계산

렌더링 영향

CSSOM 구축 완료 전까지 렌더 트리 생성 차단[4]

최적화 포인트

불필요한 규칙 제거, 미디어 쿼리 활용, 파일 크기 최소화

5. 렌더 트리 생성

렌더 트리 생성은 DOM 트리와 CSSOM 트리를 결합하여 화면에 실제로 그려질 요소들만을 포함하는 새로운 트리 구조를 만드는 과정이다. 이 트리는 렌더링 엔진이 레이아웃과 페인팅 단계를 수행하는 데 필요한 입력 데이터 역할을 한다.

렌더 트리는 시각적 요소만을 포함한다. 따라서 display: none; 속성이 적용된 요소나 <head>, <meta> 같은 비시각적 HTML 노드는 렌더 트리에 포함되지 않는다. 반면, visibility: hidden; 속성을 가진 요소는 공간을 차지하므로 렌더 트리에 포함된다. 렌더 트리의 각 노드는 일반적으로 DOM 노드에 대응되지만, 한 개의 DOM 노드가 여러 개의 렌더 트리 노드(예: 여러 줄의 텍스트)로 표현될 수도 있다.

렌더 트리의 각 노드는 해당 요소의 시각적 속성을 정의하는 스타일 정보를 포함한다. 이 과정은 다음과 같은 절차로 진행된다.

1. 브라우저는 DOM 트리의 루트부터 시작하여 각각의 가시적 노드를 순회한다.

2. 각 가시적 노드에 대해, CSSOM에서 일치하는 CSS 규칙을 찾아 스타일을 계산한다.

3. 계산된 스타일 정보를 가진 렌더 객체(또는 렌더러)가 생성되어 렌더 트리에 추가된다.

렌더 트리 특성

설명

목적

레이아웃(위치/크기 계산)과 페인트(픽셀 채우기)의 기반이 된다.

내용

페이지를 시각적으로 표현하는 데 필요한 모든 노드(텍스트, 이미지, 색상, 그림자 등)를 포함한다.

생성 순서

DOM과 CSSOM이 모두 준비된 후에 생성되기 시작한다. 따라서 CSS 로딩이 지연되면 렌더 트리 생성도 차단된다.

렌더 트리가 완성되면, 각 렌더 객체의 정확한 위치와 크기를 픽셀 단위로 계산하는 레이아웃 단계가 뒤따른다.

5.1. DOM 트리와 CSSOM 트리의 결합

DOM 트리와 CSSOM 트리는 각각 독립적으로 생성된 후, 렌더 트리를 형성하기 위해 결합된다. 이 결합 과정은 브라우저가 화면에 실제로 픽셀을 그리기 위해 필요한 모든 시각적 정보를 포함하는 하나의 트리 구조를 만드는 핵심 단계이다.

렌더 트리는 표시되는 각 요소의 시각적 표현을 담당하는 렌더 객체(또는 렌더러)로 구성된다. 결합 과정은 DOM 트리를 순회하며, 각 노드에 대해 해당하는 CSSOM 규칙을 찾아 스타일을 계산하고 적용한다. 이때 display: none;과 같은 속성을 가진 요소나 <head>, <script> 같은 비시각적 노드는 렌더 트리에 포함되지 않는다. 반면, visibility: hidden;이나 opacity: 0처럼 공간을 차지하는 요소는 보이지 않더라도 렌더 트리에 포함된다.

DOM 트리 노드 특성

CSSOM 규칙 적용

렌더 트리 포함 여부

시각적 요소 (예: <div>, <p>)

예

예

display: none; 속성

예

아니오

visibility: hidden; 속성

예

예

비시각적 요소 (예: <script>, <meta>)

아니오

아니오

스타일 계산은 종종 복잡한 과정이다. 왜냐하면 여러 CSS 선택자에 의해 정의된 규칙들이 서로 충돌할 수 있고, 캐스케이딩과 상속 규칙에 따라 최종 스타일이 결정되어야 하기 때문이다. 이렇게 계산된 최종 스타일은 각 렌더 객체에 첨부되어, 이후 레이아웃 단계에서 요소의 정확한 위치와 크기를 계산하는 데 사용된다.

5.2. 렌더 트리의 노드와 속성

렌더 트리의 노드는 렌더 객체(Render Object)라고 불리며, 이는 DOM 트리의 요소 노드와 대응되지만 완전히 일치하지는 않는다. 예를 들어, display: none 속성이 적용된 요소나 <head>, <script> 같은 메타데이터 요소는 렌더 트리에 포함되지 않는다. 반면, 텍스트 노드나 여러 줄의 텍스트는 별도의 렌더 객체로 생성될 수 있다. 각 렌더 객체는 해당 요소의 시각적 표현에 필요한 정보, 즉 CSS 박스 모델에 기반한 기하학적 속성(너비, 높이, 위치)과 스타일 정보를 담고 있다.

렌더 트리의 주요 속성은 화면에 실제로 그려질 콘텐츠의 구조와 스타일을 정의한다. 이는 CSSOM 트리와 계산된 스타일 규칙에서 비롯된다. 각 렌더 객체는 자신이 대표하는 HTML 요소의 유형(예: 블록, 인라인, 대체 요소)에 따라 특정 레이아웃 모델을 따른다. 예를 들어, 블록 렌더 객체는 수직으로 쌓이고, 인라인 렌더 객체는 수평으로 흐른다.

렌더 트리는 계층 구조를 이루며, 이는 후속 레이아웃 단계에서 각 노드의 정확한 좌표와 크기를 계산하는 기초가 된다. 최종 렌더 트리는 모든 가시 요소를 포함하지만, 보이지 않는 요소는 제외된 상태로 구성된다. 이 트리는 페인팅 단계에서 화면의 픽셀을 채우는 데 직접 사용되는 벡터 그래픽 명령어 집합인 디스플레이 리스트(Display List)를 생성하는 데 필요한 입력 자료가 된다.

6. 레이아웃(리플로우) 단계

레이아웃 단계는 렌더 트리가 생성된 후, 각 렌더 객체(노드)의 정확한 위치와 크기를 화면에 배치하는 계산 과정이다. 이 과정은 리플로우라고도 불리며, 뷰포트 내에서 모든 요소의 기하학적 속성(좌표, 치수)을 픽셀 단위로 결정한다.

레이아웃은 루트 렌더 객체에서 시작하여 재귀적으로 트리를 순회하며 진행된다. 각 노드는 자신과 자식 노드들의 상대적 또는 절대적 위치, 너비, 높이, 여백, 테두리 등을 계산한다. 이 계산은 CSS 박스 모델 규칙과 요소에 적용된 CSS 스타일, 특히 display, position, float, width, height 등의 속성에 근거한다. 레이아웃 과정은 일반적으로 전체 문서에 대해 한 번 실행되지만, 이후 JavaScript에 의한 DOM 변경이나 스타일 동적 수정, 창 크기 조절 등이 발생하면 해당 부분에 대해 리플로우가 다시 발생할 수 있다.

레이아웃 계산 요소

설명

박스 모델 속성

width, height, padding, border, margin의 계산값

위치 속성

position, top, left, right, bottom, float에 따른 좌표

뷰포트 정보

디바이스 화면 크기, 줌 레벨, 뷰포트 메타 태그 설정

리플로우는 비용이 큰 작업으로, 성능에 직접적인 영향을 미친다. 레이아웃 계산이 완료되면, 각 렌더 객체는 자신의 정확한 화면 좌표와 기하학적 정보를 가지게 되며, 이 정보는 다음 단계인 페인팅 단계에서 픽셀을 채우는 데 사용된다.

6.1. 기하학적 계산과 위치 결정

레이아웃 단계는 렌더 트리의 각 노드에 정확한 위치와 크기를 할당하는 과정이다. 이 과정은 때로 리플로우라고도 불리며, 뷰포트 내에서 모든 요소의 기하학적 속성을 계산한다. 계산 대상에는 요소의 상대 좌표, 절대 좌표, 너비, 높이, 그리고 박스 모델에 따른 마진, 테두리, 패딩, 실제 콘텐츠 영역의 크기 등이 포함된다.

계산은 일반적으로 루트 노드에서 시작하여 트리를 순회하며 수행된다. 각 노드의 위치는 CSS 박스 모델 규칙과 CSSOM에 정의된 스타일, 특히 display, position, float, width, height 등의 속성에 따라 결정된다. 예를 들어, display: block 요소는 수직으로 쌓이고, display: inline 요소는 수평으로 배치된다. position: absolute나 fixed가 적용된 요소는 일반적인 흐름에서 벗어나 특정 기준에 따라 위치가 계산된다.

레이아웃 계산은 하나의 요소에 대한 변경이 다른 요소의 위치에 영향을 미칠 수 있기 때문에 복잡한 과정일 수 있다. 한 요소의 크기가 변경되면 그 형제 요소나 부모 요소의 레이아웃이 재계산되어야 할 수 있다. 이로 인해 불필요한 리플로우가 연쇄적으로 발생하면 성능이 저하될 수 있다.

최종적으로, 이 단계를 거쳐 모든 렌더 트리 노드는 픽셀 단위의 정확한 화면 좌표와 치수를 가지게 되며, 이 정보는 다음 페인팅 단계에서 실제 픽셀을 채우는 데 사용된다.

7. 페인팅 단계

페인팅 단계는 렌더 트리가 구축되고 레이아웃(리플로우) 단계를 통해 각 노드의 정확한 위치와 크기가 계산된 후에 진행된다. 이 단계에서는 화면에 실제 픽셀을 그리는 작업이 수행되며, 때로는 래스터화(Rasterization)라고도 불린다. 페인팅은 일반적으로 여러 레이어로 나누어 처리되며, 브라우저는 z-index 속성이나 스택링 컨텍스트에 따라 이러한 레이어의 순서를 결정한다.

페인팅 프로세스는 주로 두 가지 주요 작업으로 구성된다. 첫 번째는 '페인트 기록 생성(Creating the paint records)'이다. 렌더 트리의 각 노드(렌더러)는 자신을 화면의 특정 위치에 어떻게 그려야 하는지에 대한 명령 목록, 즉 페인트 기록을 생성한다. 이 기록에는 색상, 테두리, 배경 이미지, 텍스트 등의 시각적 속성을 그리는 방법이 포함된다. 두 번째는 '래스터화(Rasterization)'로, 이러한 추상적인 그리기 명령을 실제 화면의 픽셀로 변환하는 과정이다. 최신 브라우저는 주로 GPU 가속을 활용하여 이 래스터화 작업을 수행하며, 성능을 크게 향상시킨다.

페인팅은 비용이 큰 작업이며, 전체 요소가 아닌 화면의 '더티 영역(Dirty region)'이라고 불리는 변경된 부분만을 다시 그리는 방식으로 최적화된다. 그러나 레이아웃 단계에서 기하학적 속성(너비, 높이, 위치 등)이 변경되면, 해당 요소와 자식 요소, 그리고 종종 주변 요소의 페인팅도 다시 발생해야 한다. 이를 리페인트라고 한다. 시각적 속성 중 레이아웃에 영향을 주지 않는 것(예: 배경색, 그림자, outline)만 변경된 경우에는 리플로우 없이 리페인트만 발생할 수 있다.

페인팅 성능은 CSS 속성 선택에 따라 달라질 수 있다. 예를 들어, box-shadow나 border-radius보다 transform: translate()를 사용하는 것이 일반적으로 페인팅 비용이 더 적게 든다. 브라우저의 개발자 도구에서 '페인트 플래싱(Paint flashing)' 기능을 활성화하면, 페이지 상호작용 시 어떤 영역이 다시 페인트되는지 시각적으로 확인할 수 있어 최적화에 도움이 된다.

8. 성능 최적화 기법

성능 최적화 기법은 웹 페이지의 로딩 속도를 높이고 사용자 경화를 개선하기 위해 리플로우와 리페인트 발생을 최소화하는 데 중점을 둔다. 불필요한 레이아웃 재계산과 화면 다시 그리기를 줄이는 것이 핵심이다.

CSS 최적화는 리플로우를 유발하는 속성 사용을 신중히 해야 한다. width, height, margin, padding, top, left 등의 기하학적 속성 변경은 레이아웃 재계산을 일으킨다. 대신 transform과 opacity 속성을 사용하면 컴포지터 단계에서 직접 처리되어 리플로우와 리페인트를 건너뛸 수 있다[5]. 또한, CSS 선택자를 과도하게 복잡하게 작성하면 스타일 계산 시간이 증가하므로, 간결한 선택자 사용을 권장한다.

JavaScript 최적화에서는 DOM 조작 방식을 주의해야 한다. 여러 번의 스타일 변경을 하나의 배치(batch)로 처리하거나, DOM 조작 전에 요소를 DocumentFragment에 임시로 추가하는 기법이 유용하다. 가장 무거운 작업은 requestAnimationFrame 콜백 내에서 수행하여 브라우저의 다음 리페인트 주기와 동기화하는 것이 좋다. 또한, offsetTop, scrollHeight 등 레이아웃 정보를 읽는 속성에 반복적으로 접근하면 "강제 동기 레이아웃"이 발생하므로, 값을 캐시하여 사용해야 한다.

최적화 기법

설명

주의사항

CSS transform/opacity 사용

리플로우 없이 애니메이션 가능

하드웨어 가속 지원 확인

클래스 토글을 통한 스타일 변경

여러 스타일 변경을 한 번에 적용

인라인 스타일보다 우선

DOM 조작 최소화 및 배치

DocumentFragment 사용 또는 변경 사항 축적

직접적인 DOM 반복 접근 회피

레이아웃 정보 캐싱

offsetHeight 등의 값을 변수에 저장

읽기 전에 쓰기 작업을 먼저 배치

성능 프로파일링 도구인 브라우저의 개발자 도구 Performance 패널을 사용하면 리플로우와 리페인트가 발생하는 정확한 지점과 원인을 분석할 수 있다. 이를 통해 최적화의 효과를 측정하고 병목 현상을 해결할 수 있다.

8.1. 리플로우와 리페인트 최소화

브라우저가 렌더 트리를 생성한 후 레이아웃(리플로우)과 페인팅 단계를 거쳐 화면을 그린다. 이후 DOM이나 CSS의 변경이 발생하면, 이 변경 사항이 화면에 반영되기 위해 다시 레이아웃 계산과 페인팅 작업이 필요할 수 있다. 불필요한 리플로우와 리페인트는 성능 저하의 주요 원인이므로, 이를 최소화하는 기법을 적용하는 것이 중요하다.

리플로우는 요소의 기하학적 속성(너비, 높이, 위치 등)이 변경되어 페이지의 레이아웃을 다시 계산해야 할 때 발생한다. 리플로우가 발생하면 일반적으로 뒤이어 리페인트도 필연적으로 발생한다. 반면, 리페인트는 요소의 시각적 스타일(색상, 배경, 투명도 등)만 변경되어 레이아웃 계산 없이 픽셀을 다시 그리는 경우를 말한다. 리페인트는 리플로우보다는 비용이 적지만, 여전히 성능에 영향을 미친다. 다음은 주요 최소화 기법이다.

최적화 대상

권장 기법

설명

스타일 변경

클래스 변경을 통한 일괄 처리

개별 스타일 속성을 여러 번 수정하기보다, 미리 정의된 CSS 클래스를 추가/제거하여 변경을 한 번에 처리한다.

레이아웃 트리거 방지

transform과 opacity 사용

이 속성들은 합성(compositing) 단계에서 처리되어 레이아웃이나 페인트를 유발하지 않는다. 애니메이션에 적합하다.

레이아웃 읽기/쓰기

읽기 작업 일괄화

offsetHeight, scrollTop 등의 레이아웃 값을 읽는 작업은 강제 동기 레이아웃을 유발한다. 쓰기 작업을 모두 마친 후에 일괄적으로 읽어야 한다.

DOM 조작

문서 조각(DocumentFragment) 사용

여러 DOM 요소를 추가할 때는 개별적으로 추가하지 않고, 메모리 상의 DocumentFragment에 모아 한 번에 추가한다.

레이아웃 영향 범위

영향을 받는 노드 최소화

변경이 발생한 요소의 위치를 포지셔닝(absolute, fixed)하여 리플로우의 영향을 전체 트리가 아닌 일부 서브트리로 제한한다.

성능 최적화 도구를 활용하는 것도 중요하다. 브라우저의 개발자 도구에서 Performance 패널을 사용하면 리플로우와 리페인트가 발생하는 정확한 지점과 원인을 프로파일링할 수 있다. 또한, CSS 속성 will-change를 신중하게 사용하여 브라우저에게 변경될 요소를 미리 알려 최적화할 기회를 줄 수 있다. 그러나 과도한 사용은 오히려 자원 소모를 증가시킬 수 있으므로 주의가 필요하다[6].

8.2. CSS 및 JavaScript 최적화

CSS와 JavaScript의 로딩 및 실행 방식은 렌더링 성능에 직접적인 영향을 미친다. 이들을 최적화하는 주요 기법은 렌더링 차단을 최소화하고, 불필요한 리플로우와 리페인트를 유발하지 않도록 하는 데 초점을 맞춘다.

CSS 최적화의 핵심은 CSSOM 트리 구축을 방해하지 않는 것이다. 렌더 차단 리소스인 CSS는 <head> 내에서 최대한 빨리 로드되어야 한다. 이를 위해 media 속성을 활용한 미디어 쿼리 분리는 효과적인 방법이다. 예를 들어, 인쇄용 스타일시트는 <link rel="stylesheet" href="print.css" media="print">와 같이 선언하여 화면 렌더링에는 영향을 주지 않게 한다. 또한, 과도한 셀렉터 복잡성은 스타일 계산 시간을 증가시키므로, 간결한 클래스 선택자를 우선 사용하는 것이 좋다. CSS 파일의 크기를 줄이기 위해 미니파이와 불필요한 스타일 제거도 기본적인 최적화 작업이다.

JavaScript 최적화는 주로 파싱 차단을 방지하는 데 목적이 있다. <script> 태그의 async 또는 defer 속성 사용은 필수적이다. defer는 문서 파싱 완료 후 스크립트를 실행하며, async는 스크립트 다운로드 완료 시 즉시 실행되어 파싱을 중단시킬 수 있다. 실행 순서가 중요한 스크립트는 defer를, 독립적인 스크립트는 async를 사용하는 것이 일반적이다. 또한, DOM 조작은 한꺼번에 처리하여 리플로우 횟수를 줄여야 한다. 예를 들어, 여러 요소의 스타일을 변경할 때는 클래스 토글을 사용하거나, DocumentFragment를 활용하여 DOM에 한 번만 추가하는 방식이 효율적이다.

최적화 대상

주요 기법

목적

CSS

media 속성 활용, 셀렉터 단순화, 파일 미니파이

CSSOM 구축 지연 방지, 스타일 계산 속도 향상

JavaScript

async/defer 속성 사용, DOM 조작 배치 처리, requestAnimationFrame 활용

파싱 차단 최소화, 리플로우/리페인트 트리거 감소

성능에 중요한 영향을 미치는 스타일 변경은 CSS 트리거를 고려하여 수행해야 한다. 레이아웃(기하학적 속성)을 변경하는 프로퍼티는 리플로우를 유발하지만, 페인트만 필요한 프로퍼티는 리페인트만 발생시킨다. JavaScript 애니메이션 구현 시에는 setTimeout이나 setInterval보다 requestAnimationFrame API를 사용하는 것이 브라우저의 리페인트 주기와 동기화되어 더 부드럽고 효율적이다.

9. 여담

브라우저 렌더링 과정은 기술적이지만, 그 원리를 이해하면 웹의 역사적 발전과도 연결 지어 생각해볼 수 있습니다. 초기 웹은 정적인 문서를 표시하는 데 그쳤지만, 자바스크립트와 CSS의 등장으로 동적인 콘텐츠와 복잡한 스타일링이 가능해지면서 렌더링 파이프라인의 복잡성은 기하급수적으로 증가했습니다.

이러한 복잡성은 다양한 렌더링 엔진의 등장을 불러왔습니다. 게코 엔진을 사용한 파이어폭스, 웹킷 엔진을 사용한 사파리, 그리고 이를 포크하여 개발된 블링크 엔진을 사용하는 크롬과 엣지가 대표적입니다. 각 엔진은 파싱, 레이아웃, 페인팅을 구현하는 세부 방식에 차이가 있어, 동일한 HTML 코드라도 미묘한 렌더링 결과 차이를 보일 수 있었습니다. 이는 웹 개발자가 크로스 브라우징 이슈에 대응해야 하는 주요 원인이 되었습니다.

최근의 발전 추세는 이러한 렌더링 부하를 줄이고 사용자 경험을 향상시키는 데 집중되어 있습니다. 가상 DOM을 사용하는 리액트나 뷰 같은 현대적 자바스크립트 라이브러리는 효율적인 렌더 트리 갱신을 목표로 합니다. 또한, 웹 어셈블리와 같은 기술은 복잡한 계산을 브라우저에서 더 빠르게 실행하여, 렌더링 파이프라인의 다른 단계들에 더 많은 자원을 할당할 수 있게 합니다.

시기

주요 특징

렌더링에 미친 영향

1990년대 초

정적 HTML 문서

단순한 파싱과 선형적 레이아웃

1990년대 중후반

자바스크립트, CSS 도입

동적 DOM 조작과 스타일 재계산 필요성 증가

2000년대

AJAX, 풍부한 웹 애플리케이션

부분적 렌더링과 복잡한 리플로우/리페인트 관리 중요성 대두

2010년대 이후

모던 자바스크립트 프레임워크, 웹 어셈블리

가상 DOM을 통한 효율적 갱신, 네이티브에 가까운 성능

10. 관련 문서

  • MDN Web Docs - 렌더링 성능

  • Google Developers - 브라우저의 작동 원리

  • Web.dev - Critical Rendering Path

  • Wikipedia - Web browser engine

  • Wikipedia - Document Object Model

  • W3C - HTML5 Parsing

  • Web.dev - Constructing the Object Model

  • Naver D2 - 브라우저는 어떻게 동작하는가?

리비전 정보

버전r1
수정일2026.02.13 22:16
편집자unisquads
편집 요약AI 자동 생성
히스토리로 돌아가기