reflow, repaint

HG·2022년 10월 28일
0

웹개발

목록 보기
3/5

reflow, repaint

  1. Reflow
  • 생성된 DOM노드의 레이아웃 수치(너비, 높이, 위치 등) 변경 시 영향 받은 모든 노드의 수치를 다시 계산하여, 렌더 트리를 재생성하는 과정이다.
    또한, Reflow 과정이 끝난 후, 재 생성된 렌더 트리를 다시 그리게 되는데, 이 과정을 Repatin라 한다.

  • 문서 내 노드들의 레이아웃 포지션을 재계산 후 다시 뿌려주므로 Repaint보다도 더 심각한 퍼포먼스 저하를 유발시키는 프로세스이다.

  • 특정 엘리먼트에 대해 Reflow 발생 시, 페이지에서의 해당 요소는 즉시 Reflow State가 되며, 해당 엘리먼트의 자식요소와 부모/조상 요소 역시 레이아웃 계산을 진행한다.
    결국 페이지 전체를 다시 훑는 거나 마찬가지

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

  • 어떠한 액션이나, 이벤트에 따라 HTML 요소의 크기나 위치 등 레이아웃 수치를 수정하면 그에 영향을 받는 자식 노드나 부모 노드들을 포함하여,
    Layout 과정을 다시 수행하게 됩니다. 이렇게 되면 Render Tree와 각 요소들의 크기와 위치를 다시 계산하게 됩니다.

  1. Repaint
  • Reflow 과정이 끝난 후 재 생성된 렌더 트리를 다시 그리게 되는데 이 과정을 Reapint라 한다.

  • 엘리먼트의 스킨에 변화가 발생하지만, 레이아웃에 영향을 미치지 않을 때 유발됩니다. (Visibility, outline, background-color 등 포함)
    Opera에 따르면 해당 행위가 발생하는 순간, 문서 내 DOM tree의 다른 노드들의 스킨까지도 검증해야 하므로 비용이 높다고 함

  • 레이아웃에 영향을 주지 않지만, 가시성에는 영향을 주는 엘리먼트가 변경되면 발생한다. 예를들면, opacity, background-color, visibility, outline
    Opera에 따르면, "브라우저가 DOM 트리에 있는 다른 모든 노드의 가시성을 확인해야 하므로 리페인트 비용이 많이 든다"고함

  • Reflow만 수행되면 실제 화면에 반영되지 않습니다. Render Tree를 다시 화면에 그려주는 과정이 필요하다. 결국 Paint 단계가 다시 수행되는 것

  1. Reflow가 발생하는 상황

DOM 노드의 변경: 추가, 제거 업데이트

DOM 노드의 노출 속성을 통한 변경: display:none은 reflow와 repaint를 발생시키지만, visibility:hidden은 요소가 차지한 영역을 유지해 리페인트만 발생시킨다.

스크립트 애니메이션: 애니메이션은 DOM 노드의 이동과 스타일 변경이 짧은 시간 내에 수차례 반복해 발생되는 작업이다.

스타일: 새로운 스타일시트의 추가 등을 통한 스타일 정보 변경 or 기존 스타일 규칙의 변경

사용자의 액션: 브라우저의 크기 변경, 글꼴 크기 변경

  1. Reflow를 최소화하고, 성능을 향상시키는 방법

1) Use Best-Practice Layout Techniques

  • 레이아웃을 위해 인라인 스타일이나 테이블을 사용하지 않아야 한다.

  • 인라인 스타일은 HTML이 다운로드되고, 추가 reflow 트리거 할 때, 레이아웃에 영향을 미칩니다. 테이블은 셀 치수를 계산하기 위해 파서가
    둘 이상의 패스를 필요로 하기 때문에 비용이 많이 듭니다.

  • 테이블 레이아웃 사용: fixed는 열 너비는 헤더 행 내용을 기반으로 하므로 표 형식의 데이트를 표시할 때 도움이 됩니다.

  • flexbox의 위치와 크기가 HTML이 다운로드 될 때, 변경될 수 있기 때문에 메인 페이지 레이아웃에 flex 아이템을 사용하면 성능 저하가 될 수 있다.

2) CSS 규칙의 수를 최소화한다.

  • 사용하는 규칙이 적을수록 reflow가 빨라진다. 가능한 경우 복잡한 CSS selector를 피해야한다.

  • 이 문제는 부트스트랩과 같은 프레임워크를 사용하는 경우 특히 문제가 될 수 있다. 사용되지 않는, CSS, uCss, grunt-ucss, gulp-ucss와 같은 도구는
    스타일의 도구와 파일의 크기를 상당히 줄일 수 있다.

3) DOM의 깊이를 최소화 한다.

  • DOM 트리의 크기와 각 branch의 요소 수를 줄여야한다.

4) 하단의 DOM 트리에서 클래스를 변경한다.

  • 가능한 한 최대한 하단의 DOM 트리의 요소(즉, 중첩된 하위 항목이 여러 개 없는 요소)에서 클래스를 변경한다.
    이렇게하면, reflow 범위가 필요한 만큼의 노드로 제한 될 수 있다. 본질적으로 중첩된 child 노드에 대한 영향이 최소인 경우에만 wrapper와 같은 부모 노드에 클래스 변경 사항을 적용한다.

5) 복잡한 애니메이션 flow에서 제거합니다.

  • 애니메이션이 position: absolute나 position: fixed 로 문서으ㅓㅣ flow 로 부터 제거되어, 단일 요소로 적용되어 있는지 확인합니다.
    이렇게하면 문서의 다른 요소에 영향을 주지않고 치수 및 위치를 수정할 수 있습니다.

6) 숨겨진 요소를 변경합니다.

  • display:none으로 숨겨진 요소는 변경될 때 repaint나 reflow를 유발하지 않습니다. 가능한 경우 요소를 표시하기 전에 변경합니다.

7) Batch로 요소 업데이트

-한 번의 자업으로 모든 DOM 요소를 업데이트하여 향상시킬 수 있다.

 var myelement = document.getElementById('myelement');
 myelement.width = '100px';
 myelement.height = '200px';
 myelement.style.margin = '10px';

이 케이스는 한번에 3번의 reflow를 발생시킬 수 있다.

 var myelement = document.getElementById('myelement');
 myelement.classList.add('newstyles');

 .newstyles {
     width: 100px;
     height: 200px;
     margin: 10px;
 }
  • 또한, DOM을 건드리는 시간을 최소화 할 수 있다. bullet 목록을 만들겠다고 가정하면
    각 요소를 하나씩 추가하면 한번에 최대 7개의 reflow가 발생한다. (하나의

      이 추가 될 때, 다른 하나는
    • 에 대해 3개, 텍스트에 대해 3개이다)
      그러나, DOM fragment를 사용하여 구현하고 메모리에 노드를 먼저 빌드하면, 단일 reflow가 구현 될 수 있다.

       var
       i, li,
       frag = document.createDocumentFragment(),
       ul = frag.appendChild(document.createElement('ul'));
      
       for (i = 1; i <= 3; i++) {
           li = ul.appendChild(document.createElement('li'));
           li.textContent = 'item ' + i;
       }
      
       document.body.appendChild(frag);

    8) 영향을 받는 요소를 제한한다.

    • 많은 수의 요소가 영향을 받을 수 있는 상황을 피하라. 탭을 클릭하면 다른 콘텐츠 블록이 활성화되는 갭 콘텐츠 컨트롤을 고려하시오
      각 콘텐츠 블록의 높이가 다른 경우 주변 요소에 영향을 미친다. container에 대한 고정 높이를 설정하거나 document의 flow에서 먼트롤을 제거하여 성능을 향상 시킬 수 있다.

    9) 부드러운 애니메이션은 성능을 떨어트린다는 것을 알아야한다.

    10) 브라우저 툴로 repaint 이슈 분석

    • 모든 mainstream 브라우저는 reflow가 성능에 미치는 영향을 강조하는 개발자 도구를 제공합니다. Timeline을 열고 작업을 기록해라
profile
Making Body, Making Food, Making Co?de

0개의 댓글