Front 이론

브라우저의 렌더링 과정 (CRP, Critical Rendering Path)

종구 2024. 12. 24. 16:20
CRP, Critical Rendering Path (브라우저 렌더링 과정)

출처: 인프런 - [2024] 한입 크기로 잘라먹는 리액트(React.js) : 기초부터 실전까지 (이정환 - Winterlood)

HTML > DOM
HTML 문서를 일종의 객체 모델 (Object Model)로 알기 쉽게 변환하는 과정
  •  HTML (Hyper Text Markup Language) - 하이퍼 텍스트 마크업 언어
    웹 페이지의 구조를 정의하기 위한 마크업 언어
    <html>
      <head>
        <title>My Page</title>
      </head>
      <body>
        <h1>Hello, World!</h1>
      </body>
    </html>
  • DOM (Document Object Model) - 문서 객체 모델
    HTML 문서를 브라우저가 이해할 수 있는 객체 트리 구조로 변환한 것.
    - html
      - head
        - title
      - body
        - h1

CSS > CSSOM
CSS 스타일 시트를 브라우저가 이해할 수 있는 객체 트리 구조로 변환한 것
(HTML > CSSOM 과정과 비슷하다고 보면 됨)

 

  • CSS (Cascading Style Sheet) - 계단식 스타일 시트
    HTML로 작성된 콘텐츠의 **스타일(디자인)**을 정의하는 언어
    body {
      background-color: lightblue;
    }
    h1 {
      color: navy;
    }
  • CSSOM (CSS Object Model) - CSS 객체 모델
    CSS 스타일 시트를 브라우저가 이해할 수 있는 객체 트리 구조로 변환한 것
    - body
      - background-color: lightblue
    - h1
      - color: navy
     

DOM + CSSOM = Render Tree (렌더 트리)
  • Render Tree (렌더 트리)
    웹 페이지의 청사진, 웹 페이지의 설계도 라고 생각하면 됨.
    DOM  과 CSSOM 의 모든 정보가 담겨있음

Layout
  • 웹페이지에 요소들의 배치를 잡는 작업

Painting
  • 실제로 화면에 계획된 요소들을 그려내는 작업

 


 

DOM이 수정되어서 Layout과 Painting 을 다시잡는 과정을 Reflow, Repaint 라고 부르며
화면 업데이트시 가장 오래걸리는 작업이다.
그래서 DOM의 수정이 최소화되도록 코드를 짜야한다.
( 최소화 시키기 위해선 신경을 써가며 코드를 짜야하는데, 서비스의 규모가 커질수록 신경쓰기가 매우 힘들어진다. )
예시 코드
<script>
    function onClick() {
        const $ul = document.getElementById("ul");
        for (let i=0; i<3000; i++) {
            $ul.innerHTML += `<li>${i}</li>`
        }
    }
</script>
<body>
    <button onclick="onClick()">리스트 추가하기</button>
    <ul id="ul">
    </ul>
</body>

이렇게 코드를 작성하게 되면 반복문이 1번 돌때마다 HTML 구조가 수정되고,
결과적으로 DOM 수정이 3,000번 이루어지게 된다. = Reflow, Repaint 작업이 3,000번 진행. 

성능 측정 결과 4,500ms 로 측정된다. 심하면 브라우저가 다운된다.

<script>
    function onClick() {
        const $ul = document.getElementById("ul");
        let list = "";
        
        for (let i=0; i<3000; i++) {
            $ul.innerHTML += `<li>${i}</li>`
        }
        
        $ul.innerHTML = list;
    }
</script>
<body>
    <button onclick="onClick()">리스트 추가하기</button>
    <ul id="ul">
    </ul>
</body>

list 라는 빈 변수를 선언 후, 반복문을 변수에 추가해주도록 설정한다.
이렇게 되면 list라는 변수에 3,000 번의 반복문이 돌아간 후 DOM 으로 넘어오기 때문에

DOM 수정 작업이 한번만 이루어지게 된다.
성능 또한 250ms 로 약 22배 정도 개선된다.

 

원본 출처: 인프런 - [2024] 한입 크기로 잘라먹는 리액트(React.js) : 기초부터 실전까지 (이정환 - Winterlood)