ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Reflow, Repaint
    Note 2021. 4. 23. 12:16

    reflow와 repaint는 수정된 렌더 트리를 다시 렌더링 하는 과정에서 발생하는 것으로 웹 애플리케이션의 성능을 떨어뜨리는 주된 원인 중에 하나이다. 극단적인 경우에는 CSS 효과로 인해 JavaScript의 실행 속도가 느려질 수도 있다.

     

    Repaint(리페인트)

    리페인트는 레이아웃에는 영향을 주지 않지만, 가시성에 영향을 주는 엘리먼트가 변경되면 발생한다.

    (background-color, outline, opacity 등)

     

    Reflow(리플로우)

    리플로우는 모든 엘리먼트의 위치와 길이 등을 다시 계산하는 것으로 문서의 일부 혹은 전체를 다시 렌더링 한다.

     

    단일 엘리먼트 하나를 변경해도, 하위 엘리먼트나 상위 엘리먼트 등에 영향을 미칠 수 있다.

     

    리플로우가 트리거 되는 경우

    - DOM 엘리먼트 추가, 제거 또는 변경

    - CSS 스타일 추가, 제거 또는 변경: 스타일을 직접 변경하거나, 클래스를 추가함으로써 레이아웃이 변경될 수 있음

    - CSS 애니메이션과 트랜지션: 애니메이션의 모든 프레임에서 리플로우가 발생

    - offsetWidth와 offsetHeight 사용

    - 유저 행동: 유저 인터랙션으로 발생하는 hover 효과, 필트에 텍스트 입력, 창 크기 조정, 글꼴 크기 변경, 스타일시트 또는 글꼴 전환 등을 활성화하여 리플로우를 트리거할 수 있음

     

    리플로우 방지 방법

    - 클래스 변경을 통해 스타일을 변경할 경우, 최대한 말단의 노드의 클래스를 변경

     

    - 애니메이션이 들어간 엘리먼트는 position: fixed 또는 position: absolute로 지정

      : absolute 또는 fixed 위치인 엘리먼트는 다른 엘리먼트의 레이아웃에 영향을 미치지 않는다. (리플로우가 아닌 리페인트가 발생하는데, 이것은 훨씬 적은 비용이 든다.)

     

    - 레이아웃을 위한 <table>은 피함

      : <table> 은 점진적으로 렌더링 되지 않고, 모두 불려지고 계산된 다음에서야 렌더링이 된다. 또한, 작은 변경만으로도 테이블의 다른 모든 노드에 대한 리플로우가 발생

     

    - CSS 하위 선택자를 최소화

      : 사용하는 규칙이 적을수록 리플로우가 빠름

     

    - Java Script를 통해 스타일을 변경할 경우, .cssText를 사용하거나 클래스를 변경

    var el = document.getElementById('reflow-test');
    
    el.style.padding = '8px';
    el.style.width = '320px';
    el.style.height = '240px';
    // 3번의 리플로우 발생
    
    ////
    var el = document.getElementById('reflow-test');
    
    // .cssText 사용
    el.style.cssText = 'padding: 8px; width: 320px; height: 240px;';
    // 1 번의 리플로우 발생
    
    // 클래스 변경
    el.className = 'changed';
    
    .chaged {
      padding: 8px;
      width: 320px;
      height: 240px;
    }
    // 1 번의 리플로우 발생

     

    - 캐시를 활용한 리플로우 최소화

      : 브라우저는 레이아웃 변경을 큐에 저장했다가 한 번에 실행함으로써 리플로우를 최소화하는데, offset, scrollTop과 같은 계산된 스타일 정보를 요청할 때마다 정확한 정보를 제공하기 위해 큐를 비우고, 모든 변경을 다시 적용한다. 이를 최소화하기 위해 수치에 대한 스타일 정보를 변수에 저장하여 정보 요청 횟수를 줄임으로써 리플로우를 최소화한다.

    // Bad practice
    for (let i = 0; i < len; i++) {
      el.style.top = `${ el.offsetTop + 10 }px`;
      el.style.left = `${ el.offsetLeft + 10 }px`;
    }
    
    // Good practice
    let top = el.offsetTop, left = el.offsetLeft, elStyle = el.style;
    
    for (let i = 0; i < len; i++) {
      top += 10;
      left += 10;
      elStyle.top = `${ top }px`;
      elStyle.left = `${ left }px`;
    }

     

     

     

     

    출처 : Reflow 와 Repaint / I'm Wonism!

    'Note' 카테고리의 다른 글

    DNS_PROBE_FINISHED_NXDOMAIN  (0) 2021.05.02
    Input type="date"  (0) 2021.04.28
    유닛 테스트(Unit Test), 테스트 주도 개발(Test-driven development)  (0) 2021.04.22
    Sass/SCSS  (0) 2021.04.19
    프론트엔드 개발자가 신경 써야 할 보안  (0) 2021.04.18

    댓글