요즘IT
위시켓
최근 검색어
전체 삭제
최근 검색어가 없습니다.

웹 브라우저(Web Browser)는 웹에서 페이지를 검색하고 표시하며, 사용자가 인터넷상의 다양한 정보를 탐색하고 상호작용할 수 있도록 도와주는 응용 프로그램입니다. 자주 사용되는 브라우저에는 Google Chrome, Microsoft Edge, Safari 등이 있습니다.

회원가입을 하면 원하는 문장을
저장할 수 있어요!

다음

회원가입을 하면
성장에 도움이 되는 콘텐츠를
스크랩할 수 있어요!

확인

개발

브라우저가 화면을 그리는 방법, 렌더링 과정 이해하기

년차,
어떤 스킬
,
어떤 직무
독자들이 봤을까요?
어떤 독자들이 봤는지 궁금하다면?
로그인

웹 브라우저(Web Browser)는 웹에서 페이지를 검색하고 표시하며, 사용자가 인터넷상의 다양한 정보를 탐색하고 상호작용할 수 있도록 도와주는 응용 프로그램입니다. 자주 사용되는 브라우저에는 Google Chrome, Microsoft Edge, Safari 등이 있습니다.

 

브라우저는 단순히 웹 페이지를 보는 도구가 아닙니다. 웹 서버에서 데이터를 받아 사용자에게 정보를 표시하고, 다양한 상호작용을 가능하게 하는 중요한 플랫폼입니다. 브라우저는 크게 사용자 인터페이스(주소창, 뒤로 가기 등), 렌더링 엔진, Javascript 엔진, 네트워킹, 데이터 저장소 등으로 구분할 수 있는데요. 이 중에서 이번에 다룰 내용은 바로 “렌더링 엔진”입니다.

 

렌더링(Rendering)이란, 브라우저가 HTML, CSS, Javascript를 해석해, 우리가 보는 화면에 실제로 나타내는 과정을 말합니다. 단순히 파일을 읽는 것만 아니라, 웹 페이지의 구조를 분석하고 스타일과 스크립트를 계산하며, 사용자에게 보이는 픽셀 단위의 화면을 만들어내는 아주 복잡한 과정을 의미합니다. 렌더링 과정은 브라우저의 성능을 좌우하며, 이를 이해하면 웹 페이지의 성능을 최적화하고 사용자 경험을 개선할 수 있습니다. 이번 글에서는 브라우저가 렌더링을 수행하는 단계를 하나씩 살펴보고, 자바스크립트가 렌더링에 미치는 영향과 성능 최적화 방법까지 소개해 보겠습니다.

 

브라우저 렌더링의 전체 과정

브라우저가 HTML, CSS, Javascript를 화면에 나타내기까지의 과정은 다음과 같은 단계로 이루어집니다.

 

<출처: web.dev>

 

1) HTML 파싱 및 DOM 트리 생성

가장 먼저 브라우저는 HTML 파일을 읽고 DOM(Document Object Model) 트리를 생성합니다. DOM은 HTML 문서의 계층적 구조를 표현하는 객체 모델로, 브라우저가 HTML로 작성된 여러 요소들을 Javascript가 이해하고 조작할 수 있도록 변환시킨 객체입니다.

 

DOM은 문서의 요소를 트리구조로 표현하며, 각 노드(Node)는 HTML 태그를 나타냅니다. 그리고 이 트리구조를 ‘DOM 트리’라고 부릅니다.

 

<!DOCTYPE html>
<html>
    <body>
        <div class="recipe">
            <div class="dish">삶은 계란</div>
            <div class="ingredients">계란 2개</div>
            <div class="how">15분 동안 물을…</div>
        </div>
    </body>
</html>

 

위의 코드를 DOM 트리 형태로 나타내보면 아래의 그림과 같이 나타낼 수 있습니다.

 

<출처: 작가>

 

DOM 트리는 HTML 문서를 계층적으로 표현한 트리구조로, HTML 문서의 각 요소(태그), 속성, 텍스트는 DOM 트리에서 하나의 노드로 표현됩니다. 이 트리구조 덕분에, 부모-자식, 형제 노드 간의 관계를 파악할 수 있으며, 쉽게 요소를 탐색하거나 수정할 수 있습니다.

 

2) CSS 파싱 및 CSSOM 트리 생성

HTML을 파싱해 DOM 트리를 생성했다면, 이제 브라우저는 CSS 파일을 읽어 CSSOM(CSS Object Model) 트리를 생성합니다. CSSOM은 브라우저가 CSS를 파싱하여 트리 구조로 표현한 객체 모델로, HTML 문서의 각 요소에 적용된 CSS 스타일 규칙을 나타내며, DOM과 결합해 화면에 표현될 준비를 합니다. 다음과 같은 CSS 코드가 있다고 가정해 봅시다.

 

.body{
    padding: 30px;
}
.dish {
    font-size: 20px;
}
.ingredients{
    color : blue;
}

 

그럼 CSSOM은 다음과 같이 나타낼 수 있습니다.

 

<출처: 작가>

 

3) 렌더 트리 형성

CSS를 파싱해 CSSOM까지 생성했다면, 브라우저는 이제 DOM과 CSSOM을 결합해 렌더 트리(Render Tree)를 생성합니다. 렌더 트리는 화면에 표시될 요소들만 포함하고 있으며, 각 요소에 적용될 스타일과 위치에 대한 정보를 담고 있습니다. DOM 트리와 CSSOM을 결합한 렌더 트리를 그림으로 나타내면 다음과 같습니다.

 

<출처: 작가>

 

4) 레이아웃

렌더 트리가 생성되면 브라우저는 각 요소의 위치와 크기를 계산하는 레이아웃(Layout) 단계에 들어갑니다. 이 과정에서는 요소가 화면에서 어디에 위치할지, 그리고 어떤 크기를 가질지 등을 결정합니다. 이 글에서 사용하고 있는 코드에서는 body에 padding: 30px이 적용되면, class 이름이 dish와 ingredients, how인 요소는 30px의 여백을 두고 배치되겠죠.

 

5) 페인트

레이아웃 단계 이후, 브라우저는 요소의 스타일과 내용을 바탕으로 화면에 픽셀을 그립니다. 이 단계를 페인트(Paint) 단계라고 부르며, 레이아웃 단계에서 계산된 요소들의 위치와 크기를 참고해, 각 요소에 적용된 스타일 속성(색상, 텍스트, 그림자, 테두리 등)을 시각적으로 표현합니다. 즉, 브라우저는 각 요소의 시각적인 속성을 기반으로 픽셀 데이터를 생성하며, 데이터들은 화면에 표시될 준비를 하는 단계입니다.

 

class 이름이 dish인 요소는 글자 크기 20px, 텍스트 내용은 ‘삶은 계란’으로 화면에 그려집니다. ingredients 요소는 ‘계란 2개’라는 텍스트가 파란색으로 그려지고, 마지막으로 class 이름이 how인 요소는 기본 스타일로 ‘15분 동안 물을…’이라는 텍스트가 그려지겠네요.

 

페인트 과정에서 브라우저는 각 요소의 시각적인 속성을 기반으로 페인트 레이어(Paint Layer)를 생성하는데요. 요소들의 특정 속성(z-index, position, opacity, <video>, <canvas> 등)에 따라 독립적인 레이어가 생성될 수 있습니다.

 

6) 컴포지팅

페인트 과정에서 생성된 여러 개의 레이어들은 컴포지팅(Compositing) 단계에서 하나의 화면으로 결합됩니다. 브라우저는 각 레이어를 올바른 순서로 합성해 화면에 정확히 렌더링합니다. 특히 요소가 겹치는 경우, z-index나 position과 같은 속성을 고려해 겹침 순서를 정확히 처리합니다. 여러 레이어들이 하나로 합쳐지는 과정은 아래의 그림을 보면 쉽게 이해할 수 있습니다.

 

<출처: Aerotwist>

 

예를 들어, z-index 값이 큰 요소는 더 앞쪽에 렌더링 되고, position 속성값이 fixed일 경우 독립적인 레이어로 처리되어 화면 이동과 상관없이 고정됩니다. 이러한 레이어 분리는 브라우저가 복잡한 화면을 효율적으로 처리하는 데 중요한 역할을 합니다. 예를 들어, 독립적인 레이어는 페이지의 다른 부분에 영향을 주지 않고, 개별적으로 갱신될 수 있어 레이아웃이나 페인트 작업을 최소화할 수 있습니다.

 

브라우저는 이렇게 복잡한 렌더링 과정을 통해 사용자가 보는 최종 화면을 완성합니다. 하지만 렌더링 과정에서 자바스크립트는 중요한 변수로 작용하는데요. 자바스크립트는 바로 DOM과 CSSOM에 직접적인 영향을 미치며, 브라우저가 화면을 다시 렌더링하도록 유발할 수도 있기 때문입니다. 

 

 

자바스크립트가 렌더링에 미치는 영향

그렇다면 자바스크립트는 브라우저의 렌더링 과정에 어떤 영향을 미치고, 이를 효율적으로 제어하려면 어떠한 점을 유의해야 할까요?

 

1) DOM 조작

자바스크립트는 DOM을 조작해 화면의 요소를 변경하거나 추가하는 중요한 역할을 합니다. 하지만 이러한 DOM 조작은 브라우저의 레이아웃(Layout)과 페인트(Paint) 단계를 반복적으로 실행하도록 유도하여 성능에 큰 영향을 미칠 수 있습니다.

 

리플로우는 레이아웃 단계에서 발생하는 작업으로, 요소의 크기, 위치, 레이아웃 등이 변경될 때 브라우저가 전체 레이아웃을 다시 계산하는 과정입니다. 예를 들어, element.style.width = "100px";과 같은 코드가 실행되면 해당 요소의 크기가 변경되면서 리플로우가 발생합니다. 이 과정에서 브라우저는 단순히 해당 요소뿐만 아니라, 그와 관련된 부모 요소와 자식 요소들까지 다시 계산해야 합니다. 이렇게 여러 요소에 걸쳐 레이아웃을 재계산해야 하므로, 브라우저가 처리해야 할 연산량과 계산 복잡도가 증가하게 됩니다.

 

리페인트는 레이아웃에는 영향을 주지 않지만, 요소의 시각적 스타일(예: 색상, 배경색, 테두리 등)이 변경될 때 화면에 다시 그려지는 과정을 말합니다. 리플로우에 비해 비교적 덜 복잡하지만, 빈번히 발생하면 역시 성능 저하를 초래할 수 있습니다. 따라서 DOM 조작이 필요한 경우에는 작업을 최적화하여 리플로우와 리페인트의 발생을 최소화하는 것이 중요합니다.

 

2) 스크립트 실행 차단 문제

DOM 조작 외에도 자바스크립트는 브라우저의 HTML 파싱 단계와 렌더 트리 생성 단계를 차단할 수 있습니다. 브라우저는 HTML을 파싱하면서 <script> 태그를 만나면 기본적으로 해당 스크립트를 동기적으로 실행합니다. 즉, 브라우저는 해당 스크립트를 다운로드하고 실행할 때까지 HTML 파싱을 중단합니다. 이는 렌더 트리 생성이 지연되고, 렌더링이 늦어지는 주요 원인이 될 수 있습니다.

 

특히 외부 스크립트를 로드하는 경우 네트워크 속도까지 영향을 받아 페이지가 느리게 표시되면서 사용자 경험에 부정적인 영향을 줄 수 있습니다. 이러한 문제를 줄이기 위해 <script> 태그의 async와 defer 속성을 사용합니다.

 

async는 스크립트를 비동기적으로 로드하고, 로드가 완료되는 즉시 실행하는 속성입니다. 다음과 같이 작성할 수 있습니다

<script async src="script.js"></script>

 

async 속성을 작성하면 스크립트를 비동기적으로 로드하기 때문에, HTML 파싱과 동시에 스크립트를 다운로드 및 로드합니다. 그리고 모든 스크립트가 로딩되는 즉시 스크립트를 실행합니다. 이 과정을 그림으로 나타내면 다음과 같습니다.

 

<출처: 작가>

 

async 속성은 스크립트가 로드된 즉시 실행되며, 여러 스크립트가 있을 경우 로드가 완료된 순서대로 실행됩니다. 이 때문에 실행 순서를 보장하기 어렵다는 단점이 있습니다.

 

<script> 태그의 또 다른 속성인 defer 또한 스크립트를 비동기적으로 로드하는 속성으로, 다음과 같이 작성할 수 있습니다.

 

<script defer src=”script.js”></script>

 

defer는 async와 달리, 스크립트를 비동기적으로 로드하되, HTML 파싱이 완료된 후 실행합니다. 이를 그림으로 나타내면 다음과 같습니다.

 

<출처: 작가>

 

이 속성은 여러 스크립트가 있을 경우 작성된 순서대로 실행되며, HTML 파싱과 스크립트 로드가 동시에 이루어지므로 렌더링 지연을 최소화할 수 있습니다. 이러한 특성 덕분에 async와 defer는 각각 특정 상황에서 유용하게 사용됩니다.

 

예를 들어, async는 스크립트 간 의존성이 없고, 빠르게 로드되어야 하는 스크립트에 적합합니다. 독립적인 분석 스크립트나 광고 스크립트와 같이 다른 스크립트와 상호작용을 하지 않아도 되는 경우 유용합니다. 반면, defer는 DOM이 완전히 로드된 후에 실행되어야 하거나, 스크립트 간의 실행 순서가 중요한 경우에 적합합니다. 이는 DOM과 긴밀히 연동되거나, 여러 스크립트가 서로 의존성을 가질 때 안정적인 실행을 보장합니다.

 

async와 defer를 적절히 사용하면 렌더링 성능을 최적화할 수 있으며, 스크립트 실행으로 인한 차단 문제를 효과적으로 해결할 수 있습니다. 개발 중에 각 속성의 특징을 잘 이해하고 상황에 맞게 선택하는 것이 중요합니다.

 

 

렌더링 성능 최적화 전략

자바스크립트와 브라우저의 렌더링 과정이 어떻게 상호작용을 하며, 성능에 영향을 미치는지 이해했다면 이제 렌더링 성능을 최적화하기 위한 구체적인 전략을 살펴보겠습니다. 최적화는 사용자 경험을 개선하는 핵심 요소로, 빠르고 부드러운 웹 페이지를 만드는 데 중요한 역할을 합니다.

 

1) 리플로우와 리페인트 줄이기

리플로우와 리페인트는 브라우저 성능 최적화의 주요 대상입니다. 이 두 작업이 빈번하게 발생하면 CPU와 GPU에 높은 부하를 주어 프레임 속도가 저하될 수 있습니다. 이를 최소화하는 방법 중 하나는, 바로 스타일 변경을 최소화하는 것입니다. 여러 스타일 속성을 한 번에 변경해야 하는 경우, 스타일을 모아서 변경하거나 class를 추가하여 스타일을 조정해야 합니다. 

 

또한 다음과 같이 리플로우를 발생시키는 함수나, 속성을 매번 호출하지 않고 변수에 저장해 함수의 호출을 제한하는 방법으로도 리플로우와 리페인트를 줄일 수 있습니다.

 

// bad
for (let i = 0; i< 5; i++) {
  el.style.width = target.offsetWidth + 50; // 반복문이 돌 때 매번 호출
}

// good
const { offsetWidth } = target;  // 한 번 호출해서 변수에 저장
for (let i = 0; i< 5; i++) {
  el.style.width = offsetWidth + 50;
}

 

2) 이미지와 리소스 최적화

웹 페이지에서 이미지는 시각적으로 중요한 요소지만, 파일 크기가 커 로딩 속도에 큰 영향을 미칩니다. 특히 사용자가 즉시 보지 않는 이미지를 미리 로드하면, 불필요한 네트워크 요청과 자원 소비로 인해 페이지 로딩 속도가 느려질 수 있습니다. 이러한 문제는 Lazy Loading을 사용해 해결할 수 있습니다.

Lazy Loading은 사용자가 해당 콘텐츠를 실제로 볼 때 이미지를 로드하는 기술로, 초기 로딩 속도를 크게 개선할 수 있습니다. HTML5에서는 이를 간편하게 구현할 수 있는 loading 속성을 제공하기 때문에 다음과 같이 아주 간단하게 사용할 수 있습니다.

 

<img src="example.jpg" alt="Example Image" loading="lazy">

 

위와 같이 이미지 태그에 loading="lazy" 속성을 추가하면, 브라우저는 사용자가 해당 이미지를 볼 위치에 도달할 때 이미지를 로드합니다. 이로 인해 네트워크 요청을 줄이고, 초기 렌더링 속도를 높여 사용자 경험을 개선할 수 있습니다.

 

3) CSS와 JS 로드 방식 최적화

CSS와 JS 파일이 로드되고 실행되는 방식 또한 페이지 렌더링 성능에 중요한 영향을 미칩니다. 이를 최적화하는 방법에는 다음과 같은 방법이 있습니다. 먼저 CSS 파일을 최적화하는 방법입니다. CSS는 HTML 문서를 파싱하기 전에 로드되어야 하므로, CSS 파일은 rel=”stylesheet” 속성을 통해 <head> 태그 내부에 포함해야 합니다.

 

앞서 살펴본 async와 defer 속성을 적절히 활용하는 것도 JS 파일 로드 방식을 최적화하는 방법 중 하나입니다. async 속성은 독립적인 스크립트를 빠르게 실행해야 할 때, defer 속성은 DOM과 함께 실행되어야 하는 스크립트를 처리할 때 적합합니다.

 

 

마치며

이처럼 브라우저의 렌더링 과정과 자바스크립트의 역할을 이해하면, 성능 저하의 원인을 분석하고 사용자 경험을 크게 개선할 수 있습니다. DOM 조작과 스크립트 실행 최적화, 리소스 최적화를 통해 페이지 로딩 속도를 높이고, 브라우저의 부하를 줄일 수 있죠.

 

렌더링 최적화는 단순히 페이지 속도를 높이는 데 그치지 않고, 부드럽고 매끄러운 사용자 경험을 제공하는 핵심적인 작업입니다. 지금까지 살펴본 내용을 바탕으로 웹 개발 과정에서 렌더링 성능을 신경 쓴다면, 사용자와 개발자 모두에게 만족스러운 결과를 가져올 수 있습니다. 앞으로 브라우저 렌더링 과정을 깊이 이해하고 이를 활용한다면, 더욱 빠르고 매끄러운 사용자 경험을 제공하는 웹 사이트를 구현할 수 있을 것으로 기대합니다.

 

요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.

좋아요

댓글

공유

공유

프론트엔드 개발자 | 교육자
10
명 알림 받는 중

작가 홈

프론트엔드 개발자 | 교육자
10
명 알림 받는 중
프론트엔드 개발자를 꿈꾸는 분들을 위해, 강의와 도서로 지식을 공유하고 있습니다.

좋아요

댓글

스크랩

공유

공유

요즘IT가 PICK한 뉴스레터를 매주 목요일에 만나보세요

요즘IT가 PICK한 뉴스레터를
매주 목요일에 만나보세요

뉴스레터를 구독하려면 동의가 필요합니다.
https://auth.wishket.com/login