ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 브라우저 렌더링 과정
    FE/HTML 2025. 8. 19. 22:46

    🌐 브라우저 렌더링 과정

    렌더링이란 브라우저가 HTML, CSS, Javascript를 해석해 우리가 보는 화면이 실제로 나타나는 과정입니다.

     

    🏃 렌더링 과정

    브라우저가 HTML, CSS, Javascript를 화면에 나타내는 과정은 다음과 같습니다.

     

    1️⃣ HTML 파싱 및 DOM 트리 생성

    먼저, 브라우저는 HTML 파일을 읽고 해석하여 DOM (Document Object Model) 트리를 구성합니다.

    📖 HTML 파싱

    • 웹 브라우저가 서버에서 받은 HTML 문서를 문자열로 받아 이를 파싱하여 이해 가능한 구조로 변환하는 과정
    • 브라우저는 HTML 문서를 위에서 아래로 읽어 태그와 내용을 파악하고 각 요소의 의미와 관계를 이해

    🌴 DOM Tree

    • HTML 문서의 계층적 구조를 표현한 객체 모델
    • 브라우저가 HTML로 작성된 여러 요소들을 Javascript가 이해하고 조작할 수 있도록 변환시킨 객체

     

    즉, HTML 문서를 객체로 표현해 Javascript 같은 스크립트 및 프로그래밍 언어가 웹 페이지에 접근할 수 있습니다.

     

    🔗 DOM은 HTML로 구성된 웹페이지와 프로그래밍 언어를 연결시켜주는 역할

     

    🌱 HTML - DOM 트리 예제

    <!DOCTYPE html>
    <html>
        <body>
          <div class="div">
              <div class="first">hello</div>
              <div class="second">world</div>
              <div class="third">!</div>
        </body>
    </html>

     

    이 HTML을 DOM 트리 형태의 그림으로 나타내면 아래와 같습니다.

     

    이렇게 DOM 트리는 HTML 문서를 계층적으로 표현한 트리구조입니다.

    • HTML 문서의 각 요소(태그), 속성, 텍스트(내용)은 DOM 트리에서 하나의 노드로 표현됩니다.
    • 이를 통해 부모-자식, 형제 노드간의 관계를 파악해 요소를 탐색하거나 수정할 수 있습니다.

     

    🏄‍♂️ DOM 생성 과정

     

    📍바이트(Bytes) → 문자(Characters)

    • 브라우저가 서버로부터 HTML 문서를 바이트(Bytes) 형태로 전달받습니다.
    • 이 바이트들을 인코딩(예: UTF-8) 정보에 따라 개별 문자(Characters)로 변환합니다
      • meta 태그의 charset 어트리뷰트로 지정해둔 인코딩 방식

     

    📍문자(Characters) → 토큰(Tokens)

    • 문자열을 HTML 사양에 정의된 토큰(Tokens)으로 분해합니다.

     

    📍토큰(Tokens) → 노드(Nodes)

    • 토큰들이 계층적인 구조를 가진 노드(Nodes)로 변환됩니다.
    ex) <p class="title">Hello, World!</p>
    ----
    <p> 노드
    class 속성 노드
    "title" 속성 값 노드
    "Hello World!" 텍스트 노드

     

    📍노드(Nodes) → DOM 트리(DOM Tree)

    • 모든 노드들이 서로 부모-자식-형제 관계를 형성하며 하나의 DOM 트리(DOM Tree)를 구성합니다.
    • 이 트리의 가장 위에는 document 객체가 존재하며 그 아래에 <html> 요소가 루트 노드로 위치

     

    🔍 HTML 파싱 도중 script 태그를 만나면??

    HTML 웹 페이지는 HTML 파서에 의해 DOM으로 변환됩니다.

     

    🤔 하지만 이 과정에서 파서가 script 태그를 만나면 어떻게 될까요?

    > 파서는 DOM 생성을 중지하고 자바스크립트 엔진이 script에 정의된 파일 및 코드를 실행하고 스크립트 실행이 완료되면 다시 HTML 파서가 DOM 생성을 다시 시작합니다.

     

    script 태그는 HTML 파싱에 블로킹(blocking) 요소로 작용합니다.

     

    브라우저는 script 태그를 만나면 현재까지 파싱한 HTML 문서의 DOM 구조가 변경될 수 있다고 가정합니다.

    • ex) document.write() → DOM 수정

     

    즉, 브라우저는 동기적으로 HTML과 JavaScript를 처리하기 때문에 script 태그의 위치에 따라 DOM 생성이 느려질 수 있어요.

    따라서 일반적으로 script태그 는 HTML 문서 하단에 넣어 HTML 파싱이 완료된 후에 스크립트가 실행되도록 합니다.

    • DOM 생성이 지연되지 않고 스크립트에 DOM으로 접근하는 코드가 있다면 제대로 실행되지 않기 때문입니다.

     

    반면, link 태그 (CSS 파일)와 style 태그 (내부 CSS)는 script 태그와 다르게 HTML 파싱을 차단하지 않습니다.

    • 브라우저는 CSS 파일을 다운로드하면서 동시에 HTML 파싱을 계속 진행합니다.
    • CSS 파일이 다운로드되면 브라우저는 이를 파싱하여 CSSOM을 생성합니다.

     

    2️⃣ CSS 파싱 및 CSSOM 트리 생성

    HTML을 파싱한 후 DOM 트리를 생성했다면 브라우저는 CSS 파일을 읽어 CSSOM(CSS Objeect Model) 트리를 생성합니다.

     

    📖 CSSOM

    • 브라우저가 CSS를 파싱해 트리구조로 표현한 객체모델
    • HTML 문서의 각 요소에 적용된 CSS 스타일 규칙을 나타내고 DOM과 결합해 화면에 표현됩니다.

     

    🎨 CSS - CSSOM 예제

    .body {
        padding: 10px;
    }
    .first {
        font-size: 10px;
    }
    .second {
        color: blue;
    }

     

     

     

     

    3️⃣ 렌더 트리 형성

    Style Computing

    • CSSOM 을 이용해 계산된 스타일 객체를 생성
    • DOM을 순회하며 CSSOM의 셀렉터와 노드를 매칭하여 노드의 스타일을 확정
    • 하나의 객체로 구조화 ⇒ 개선된 스타일 객체

     

    DOM Tree와 CSSOM Tree가 만들어졌으면 그 다음으로는 이 둘을 이용하여 Render Tree를 생성합니다.

     

    순수한 요소들의 구조와 텍스트만 존재하는 DOM Tree와는 달리 Render Tree에는 스타일 정보가 설정되어 있으며 실제 화면에 표현되는 노드들로만 구성됩니다.

    • DOM 트리 + 계산된 스타일 객체

     

    ⚠️ 실제로 화면에 보여지지 않는 요소의 경우에 렌더트리 단계에서 사라집니다.

    display:none CSS spec에서 레이아웃을 생성하지 않도록 규정
    <input type=”hidden” /> display:none 이 적용되어 있는 것으로 간주
    <head /> 실제로 화면에 그려지는 시각적 요소가 아님

     

     

     

    4️⃣ Layout

    렌더 트리가 생성되면 브라우저는 각 요소의 위치와 크기를 계산하는 레이아웃 단계에 들어가게 됩니다.

    • 화면에 표시될 상자 크기를 결정
    • 렌더 트리를 순회하며 노드의 너비, 높이, 위치등을 결정

     

    5️⃣ Paint & Rasterization

    🎨 Paint

    렌더 트리를 순회하며 노드별 페이팅 정보를 담은 페인트 레코드 생성

     

    🖌️ Rasterization

    • 페인트 레코드를 그룹으로 묶어 레이어를 생성 후 레코드를 픽셀로 변환

    📖 페인트 레코드

    • 실제 화면에 그리기 위한 명령

     

    레이아웃 단계에서 계산된 요소들의 위치와 크기, 계산된 스타일이 적용된 렌더 트리를 이용해 스타일 속성을 시각적으로 표현합니다.(텍스트, 색, 그림자, 효과 등)

     

    처리해야 하는 스타일이 복잡할수록 소요되는 시간이 늘어나게 됩니다.

    • ex)  background-color의 경우 속도가 빠르지만 그라데이션이나 그림자 효과등은 painting 시간이 더 오래 걸립니다.

     

    6️⃣ Compositing

    페인트 과정에서 생성된 여러 개의 레이어들은 컴포지팅 단계에서 하나의 화면으로 조합합니다.

    브라우저는 각 레이어를 순서대로 합성하여 화면에 정확히 렌더링합니다.

     

    https://www.youtube.com/watch?v=heoTDzJx_Gw&t=319s&ab_channel=우아한테크

     

     

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

    🎛️ DOM 을 조작

    자바스크립트는 DOM을 조작해 화면의 요소를 수정하거나 추가합니다.

    이런 조작 작업은 브라우저의 레이아웃과 페인트 단계를 반복하도록 해 성능에 영향을 미칠 수 있습니다.

     

    📖 Reflow

    • 레이아웃 단계에서 발생하는 작업으로 요소의 크기, 위치, 레이아웃 등이 변경될 때 브라우저가 전체 레이아웃을 다시 계산하는 과정
    reflow() {
      document.getElementById("content").style.width = "100px";
    }

     

    위와 같은 코드가 실행되면 해당 요소의 크기가 변경되면서 reflow가 발생합니다.

    • 브라우저는 해당 요소뿐만 아니라 그와 관련된 부모, 자식 요소들까지 다시 계산
    • 여러 요소에 대한 레이아웃을 재계산해야 하므로 브라우저가 처리해야 할 연산, 복잡도가 증가합니다.

     

    📖 Repaint

    • 레이아웃에는 영향을 주지 않지만 요소의 시각적 스타일(색상, 테두리 등)이 변경될 때 화면에 다시 그려지는 과정
    • reflow에 비해는 덜 복잡하지만 많이 발생하면 성능 저하 발생

    ⭐ 따라서 DOM 조작이 필요할 경우에는 이런 작업을 최적화해 reflow, repaint의 발생을 최소화하는 것이 중요!!!

     

    🚫 스크립트 실행 차단 문제

    아까 말한 것처럼 자바스크립트는 브라우저의 HTML 파싱 단계와 렌더 트리 생성단계를 차단할 수 있습니다.

    HTML을 파싱하면서 <script> 태그를 만나면 해당 스크립트를 동기적으로 실행하여 해당 스크립트를 다운로드하고 실행할 때까지 HTML 파싱을 중단하여 렌더 트리 생성이 지연되고 렌더링이 늦어지는 원인이 됩니다.

     

    ⭐ 이런 문제를 줄이기 위해서 <script> 태그의 async, defer 속성을 사용합니다.

     

    ✅ async

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

    async 속성을 사용하면 스크립트를 비동기적으로 로드하기 때문에 HTMl 파싱과 동시에 스크립트를 다운로드 및 로드를 합니다.

    • 모든 스크립트가 로딩되는 즉시 스크립트를 실행

     

    ⚠️ async는 스크립트가 로드된 즉시 실행되어 여러 스크립트가 있을 경우 로드가 된 순서대로 실행되기 때문에 실행 순서를 보장하기 어렵습니다.

     

    ✅ defer

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

     

    defer는 async와 달리 스크립트를 비동기적으로 로드해 HTML 파싱이 완료된 후 실행합니다.

     

     

    async 와 달리 여러 스크립트가 있을 때 순서대로 실행되고 HTML 파싱과 스크립트 로드가 동시에 실행되어 렌더링 지연을 최소화할 수 있습니다.

    async와 defer의 이런 특성등을 적절히 사용하면 렌더링 성능을 최적화하고 스크립트 실행으로 인한 차단문제를 해결할 수 있습니다.

     

    👍 렌더링 성능 최적화

    1️⃣ 리플로우와 리페인트 줄여보기

    리플로우와 리페인트가 빈번하게 발생하면 CPU와 GPU에 높은 부하가 발생해 프레인 속도가 저하될 수 있습니다.

    따라서 스타일 변경을 최소화하는 것이 중요합니다.

    • 여러 스타일 속성을 한 번에 변경해야 하는 경우 스타일을 모아서 변경하거나 class를 추가해 스타일을 조정

     

    2️⃣ 이미지와 리소스 최적화

    이미지는 파일 크기가 커 로딩 속도에 큰 영향을 미칩니다.

    현재 보지 않는 이미지를 미리 로드하게 되면 불필요한 네트워크 요청과 자원 소비로 인해 페이지 로딩 속도가 느려질 수 있습니다.

     

    이 문제를 해결하기 위해 Lazy Loading을 사용해 해결할 수 있습니다.

     

    <img src="image.jpg" alt="sample image" loading="lazy">

    이미지 태그에 loading=”lazy” 속성을 추가해 브라우저는 사용자가 해당 이미지를 볼 때 이미지를 로드하도록 합니다.

     

    이를 통해 네트워크 요청을 줄이고 초기 렌더링 속도를 높여 사용자 경험을 개선할 수 있습니다.

     

    3️⃣ CSS와 JS 로드 방식 최적화

    CSS, JS 파일 로드되고 실행되는 방식도 페이지 렌더링 성능에 영향을 미칩니다.

    CSS는 HTML 문서를 파싱하기전에 로드되어야 하기 때문에 CSS 파일은 rel = “stylesheet” 속성을 통해 <head> 태그 내부에 포함되도록 합니다.

     

    'FE > HTML' 카테고리의 다른 글

    브라우저 이벤트  (4) 2025.08.26
    CSS 알아보기  (2) 2025.08.25
    브라우저 렌더링 방식 (SSR, CSR)  (0) 2025.08.20
    HTML 기본 정리  (1) 2025.08.18

    댓글

Designed by Tistory.