Reflow와 Repaint

Minsu·2024년 10월 9일

Reflow, Repaint란?


먼저, 브라우저 렌더링 순서를 알아보자.

  1. 사용자가 브라우저를 통해 사이트에 접속
  2. HTML, CSS, JS 등 필요한 리소스를 서버에 요청
  3. 네트워크 통신을 마친 후, Parse, Layout, Paint, Composite 네 가지 과정을 거쳐 화면을 렌더링하게 된다.
    1. HTML 파싱을 통해 DOM 트리 생성
    2. CSS 파싱을 통해 CSSOM 트리 생성
    3. DOM 트리와 CSSOM 트리를 조합하여 렌더 트리 생성
      • 이 때, 렌더링 되어야 할 요소들만 렌더 트리에 포함된다. display: none 과 같이 화면에 보이지 않는 요소는 렌더 트리에 포함되지 않는다.
    4. 레이아웃
    5. 페인트

Reflow

  • 레이아웃을 다시 계산하는 과정으로, Layout 단계에 해당한다.
  • 특정 CSS 속성의 변경, 또는 DOM 구조의 변경 등 구조적인 변화가 있는 경우 수행된다.
    • 브라우저가 레이아웃을 다시 계산해야 하기 때문
  • e.g. 화면 크기 변경, 폰트 크기 조정, 요소 위치 변경, 브라우저 창 크기 변경, 스크롤 이벤트 발생, DOM API를 통한 노드 요소의 추가, 삭제
  • Reflow를 일으키는 요소들
    position, width, height, margin, padding, 
    border, border-width, font-size, font-weight, 
    line-height, text-align, overflow, 
    top, left, right, bottom 
    ...

Repaint

  • 요소의 스타일만 변경되었을 때 수행되며, Paint 단계에 해당한다.
  • e.g. 배경색, 텍스트 색상 등 레이아웃의 변화 없이 스타일만 변경될 경우
  • reflow는 반드시 repaint를 동반하기 때문에 reflow 발생 시 repaint만 발생하는 것보다 더욱 소모적일 수 있다.
  • Repaint를 일으키는 요소들
    background, color, text-decoration
    border, outline, visibility
    ...

그렇다면, 최적화 방법은?


  • 레이아웃 변경 최소화하기

    • 일차적으로, width와 height등과 같은 기하학적 속성의 변경을 피하자.
    • 변경이 불가피하다면, top, left 대신 translate css 속성을 사용해 위치 변경하기.
  • display: none 사용 자제하기

    • display: none을 설정하거나 해제하면 브라우저가 해당 요소를 레이아웃에서 제거하고 다시 계산해야 한다.
    • visibility: hidden 으로 대체하여 사용하기.
  • CSS 속성 축약 및 리팩토링

    • 중복된 CSS 속성들을 축약하고, 불필요한 속성을 없애자.
    • e.g.
      • CSS 축약같은 속성들이 반복된다면 축약형 속성을 사용
        /* 축약 전 */
        padding-top: 4px;
        padding-right: 4px;
        padding-bottom: 4px;
        padding-left: 4px;
        
        /* 축약 후(최적화) */
        margin: 4px;
        
    • 불필요한 @media 쿼리 최소화
      • 여러 개의 미디어 쿼리를 사용하는 대신, 비슷한 조건의 미디어 쿼리는 하나로 묶어서 관리한다.
  • flex, grid 사용하기

    • 이전 레이아웃(e.g. float) 대신 flexbox와 gird를 사용하면 reflow 시간을 단축할 수 있다.
  • Lazy Loading 사용하기

    • 페이지에 당장 필요하지 않은 리소스는 스크롤될 때 로드되도록 설정한다. → 초기 로딩 속도를 줄일 수 있다.
  • 애니메이션, 트랜지션 최적화 → GPU 가속 적용하기

    • 애니메이션에 사용해야 할 속성: transform, opacity
      • GPU 가속을 사용해서 처리되기 때문에 성능에 부담을 주지 않고, 레이아웃 변경 없이 애니메이션을 부드럽게 적용할 수 있다.
      • opacity: 1 로 적용할 경우 GPU가 트리거되지 않아 레이아웃 단계가 발생하게 된다. 이 경우 opacity: 0.99 로 바꾸면 reflow가 발생하지 않는다.
    • 피해야 할 속성: width, height, margin, padding, top, left
      • 레이아웃을 다시 계산해야 하기 때문에 성능에 좋지 않다.
  • CSS will-change 속성 사용하기

    • 브라우저에게 미리 어떤 속성이 변경될지 알려주는 역할을 한다.
      • 브라우저가 해당 요소에 GPU 가속을 미리 적용하여 성능 최적화가 가능하다.
    • 변경되지 않을 모든 요소까지 미리 적용할 시 불필요한 메모리 점유로 성능 저하가 발생할 수 있다.
    • will-change보다는 CSS를 통한 animation과 transition을 우선 시도하자.
  • CSS contain 속성 사용하기

    • 특정 요소를 문서 트리에서 독립되어 있음을 나타낼 때 사용하며, 연산 과정을 격리시킬 수 있다.

      /* 키워드 값 */
      contain: none;      /* 격리없이 평범하게 렌더링함 */
      contain: strict;    /* style을 제외한 모든 격리 규칙을 적용함 */
      contain: content;   /* size와 style을 제외한 모든 격리 규칙 */
      contain: size;      /* 요소의 크기를 계산할 때 자손의 크기는 고려하지 않아도 됨을 나타냄 */
      contain: layout;    /* 요소 외부의 어느 것도 내부 레이아웃 영향을 주지 않음 */
      contain: style;     /* 요소 자신과 자손 외에도 영향을 주는 속성이라도 그 영향 범위가 자신을 벗어나지 않음 */
      contain: paint;     /* 요소가 화면 밖에 위치할 경우 당연히 그 안의 자손도 화면 안에 들어오지 않을 것이므로 브라우저는 그 안 요소 고려하지 않음 */

      *출처: https://frontdev.tistory.com/entry/CSS-Contain-속성에-대하여

GPU 가속이란?
브라우저가 애니메이션이나 그래픽 작업을 처리할 때 CPU 대신 GPU(Graphics Processing Unit)를 활용해서 성능을 최적화하는 방법. GPU는 복잡한 그래픽 연산을 빠르게 처리할 수 있기 때문에, 특히 애니메이션이나 복잡한 시각적 효과에서 중요한 역할을 함.

참고 자료

profile
지식의 해상도를 높여가는 개발자 (っ'-')🖥️

0개의 댓글