WEB 브라우저 렌더링과 웹 렌더링 방식들 개념 요약 정리

작성 : 2023-09-10수정 : 2023-09-21

목차 펼치기

브라우저 렌더링 (Browser Rendering)

Google Chrome, MS Edge, Naver Whale은 Blink, Safari는 Webkit, Firefox는 Gecko 렌더링 엔진을 사용하고 있다. 엔진마다 차이는 있을 수 있으나 전반적인 브라우저 렌더링 순서는 다음과 같다.



렌더링 순서

  1. HTML 코드를 해석해 DOM Tree로 변환

  2. 스타일시트를 해석해 CSSOM Tree 생성

  3. DOM Tree와 CSSOM Tree를 결합하여 Rendering Tree 생성

    • 페이지를 렌더링 하는 데 필요한 노드만 포함한다.

    • display: none

      과 같이 숨겨진 요소는 제외된다.

  4. Layout

    • Viewport 내 각 요소의 위치와 크기 계산

    • 상대값은 이 때 고정된 픽셀로 변환된다.

    • 노드 수가 많을 수록 오래걸리고, 레이아웃 병목현상으로 스크롤이나 기타 애니메이션 동작에 렉이 발생할 수 있다.

    • 크롬 개발자도구 [Layers] 탭에서 생성된 레이어 층을 확인할 수 있다.

      • [더보기] - [More tools] - [Layers]

    • 크롬 개발자도구 [Performance] - [Event Log]에 “Layout”으로 기록되는걸 볼 수 있다.

  5. Paint

    • Rendering Tree의 각 노드를 화면의 실제 픽셀로 변환한다.

    • Layout 단계에서 계산된 결과를 이용해 화면에 그리는 과정이다.

    • 변환된 픽셀 결과를 바탕으로 여러 개의 레이어가 발생한다.

      • 일반적으로

        position

        ,

        z-index

        ,

        transform

        ,

        filter

        ,

        canvas

        ,

        video

        속성을 기준으로 나뉜다.

      • 이 레이어를 기준으로 Repaint가 발생한다.

      • wil-change

        속성을 이용해 별도로 레이어를 구성할 수 있다.

    • 페인트 레코드를 생성한다.

      페인트 레코드 : 요소의 배치 등 렌더링 순서를 기록한 정보

    • 크롬 개발자도구 [Performance] - [Event Log]에 “Paint”로 기록되는걸 볼 수 있다.

  6. Composition

    • Composite Layers를 만들어 최종 화면을 그린다.

      Composite Layers : 페인트 단계에서 생성된 레이어들의 합성


이후 특정 속성이 수정되거나 메소드가 실행될 때 Reflow 또는 Repaint 동작이 수행된다.

이 동작들은 UI 렌더링 성능에 영향을 미칠 수 있기 때문에 UX를 고려한다면 최소화해야한다.


Reflow

  • 노드의 크기나 위치가 변경되어 배치를 다시 해야할 때 발생한다.

    • Layout - Paint 과정이 다시 수행되는 것과 같다.

    • 반드시 Repaint가 따라서 발생한다.

  • 다른 노드와의 관계에 따라 추가 Reflow를 유발할 수 있어 DOM 전체에서 Reflow가 발생할 수도 있다.

  • position

    ,

    width

    ,

    height

    ,

    margin

    ,

    padding

    ,

    border

    ,

    border-width

    ,

    font-size

    ,

    font-weight

    ,

    line-height

    ,

    text-align

    ,

    overflow

    등의 속성이 변경되었을 때 발생된다.

  • clientHeight

    ,

    offsetHeight

    ,

    scrollHeight

    등의 속성이 변경되었을 때 발생된다.

  • getBoundingClientRect()

    ,

    getClientRect()

    ,

    scrollTo()

    등의 메소드가 실행될 때 발생된다.


Repaint

  • Reflow가 발생하거나 색상처럼 단순한 스타일을 변경할 때 발생한다.

    • Paint 과정을 다시 수행하는 것과 같다.

  • background

    ,

    color

    ,

    text-decoration

    ,

    border-style

    ,

    border-radius

    등의 속성이 변경되었을 때 발생된다.


렌더링 최적화

렌더링 성능을 위한 Reflow와 Repaint 최적화 방안으로는 다음과 같다.


  • 비슷한 형태의 작업은 묶어서 실행될 수 있도록 코드 순서를 배치한다.

  • 스타일 수정은 Callback Queue가 아니라 Call Stack에서 바로 실행될 수 있도록 처리한다.

    • Callback Queue는 이벤트 루프에 따라 비동기적으로 실행되어 리렌더링이 추가로 발생할 수 있다.

  • display: none

    을 활용하여 노출을 최소화 한 후 스타일을 변경하여 다시 최종 반영한다.

  • 노드를 복제하여 스타일을 수정한 후 기존 노드와 치환한다.

  • createDocumentFragment()

    함수를 통해 메인 DOM 과 별개의 DOM을 만들어 작업 후 메인 DOM에 추가한다.

  • Reflow를 유발하는 특정 속성이나 함수의 값은 별도의 변수에 저장한 후 사용한다.

    • getBoundingClientRect()

      등의 함수 같은 경우 실행될 때마다 Reflow가 발생한다.

  • 대상 노드의 개수가 많을수록 JavaScript보다 CSS 규칙을 통해 반영한다.

    • 일반적으로 JavaScript로 처리하는 것은 CSS보다 느리고 사이트렉을 유발할 수 있다.

      • 비동기 작업이나 상호작용이 필요한 요소는 JavaScript로 스타일을 수정하는 것이 적합할 수도 있다.

    • 다음과 같은 이유로 CSS로 가능한 작업들은 되도록 CSS로 진행해야 한다.

      • 최적화된 엔진

        • 브라우저는 CSS 스타일 변경에 최적화된 엔진을 가지고 있다.

        • JavaScript를 사용할 경우 JavaScript 엔진과 스타일 엔진 간 상호작용으로 처리가 지연된다.

      • 일괄 처리

        • CSS는 여러 요소에 대한 스타일 변경을 일괄 처리할 수 있어 효율적이다.

      • 메모리 사용 최적화

        • CSS는 브라우저의 스타일 시트에 스타일 규칙을 적용하기 때문에 메모리 최적화가 되어 있다.

        • JavaScript 스타일 변경 이력은 JavaScript 메모리에 저장되기 때문에 메모리 사용량이 늘어날 수 있다.

      • 구조와 스타일 분리

        • CSS를 통해 HTML과 스타일이 분리되어 가독성이 향상되고 유지보수가 쉬워진다.

        • JavaScript로 스타일을 변경하는 것은 구조와 스타일을 혼합시켜 코드 복잡도를 향상시켜 오류를 야기할 수 있다.

  • HTML 마크업을 구조적으로 최적화 한다.

    • 불필요한 wrapper가 있다면 제거한다

  • 사용하지 않는 CSS 선언은 제거한다.

    • 크롬 개발자도구 [CSS Overview] - [Unused delarations] 에서 확인할 수 있다.