새소식

프론트엔드 공부/Web Server

리플로우(Reflow)와 리페인트(Repaint)

  • -

웹페이지(브라우저) 렌더링 과정

렌더링 엔진은 HTML 파일과 SytyleSheet를 해석해서 렌더트리를 만든다.

HTML 해석 -> DOM Tree         
SytyleSheet 해석 -> CSSOM Tree          // CSS Object Model  
DOM Tree + CSSOM Tree -> Render Tree

Render Tree는 화면에 표시되는 모든 노드의 컨텐츠와 스타일 정보를 포함하고있고 렌더트리가 형성되면 레이아웃 단계로 진행이 된다.

브라우저 내에서 뷰포트와 노드들의 정확한 위치와 크기들을 계산하는 단계를 레이아웃(Layout)이라고 하고 전문용어로 리플로우(Reflow)라고 합니다.  Reflow(Layout이라고도 함), Repaint(Redraw라고도 함) 

그런데 브라우저 렌더링 과정과 reflow, repaint는 무슨 관계가 있는걸까?

reflow, repaint를 알기위해, Layout, paint 부분이 중요하다.
Layout는 앞서 설명했듯이 요소의 위치, 크기를 계산하여 화면에 그리는 과정인데, reflow와 관련있다.paint는 배치된 요소에 스타일(색상, 굵기 등)을 적용하는 과정으로 repaint와 관련있다.

우선 reflow는 말 그대로, flow과정을 다시 하는 작업이다.
flow작업은 곧 layout이며, reflow가 된다는 건 요소의 위치, 크기 계산을 다시 한다는 말이 된다.
repaint는 paint 작업을 다시 하는 걸 말한다. paint는 요소에 스타일을 적용하는 과정이므로, repaint는 요소의 스타일을 재적용하는 걸 말한다.

결국 reflow, repaint는 이 브라우저 렌더링의 일부 과정을 다시하는 걸 말한다.

리플로우란?

생성된 DOM 노드의 레이아웃 수치(너비, 높이, 위치 등) 변경시 영향을 받은 모든 노드의 수치를 다시 계산하여 렌더트리를 재생성 하는 과정

리플로우의 주요 키 포인트는 레이아웃에 있습니다. 레이아웃이 끝나면 색칠을 해주는 리페인트가 필요합니다.


리페인트란?

리플로우 과정이 끝난 후 재생성된 렌더 트리를 다시 그리(paint)는 과정.(변경된 요소를 화면에 그려주는 작업.)

* 그러나 레이아웃 수치가 변경되어야만 리페인트가 발생하는 것은 아닙니다. 노드의 backgorund-color, visibility, outline 등의 스타일이 변경되었을 때는 Reflow 빼고 Repaint만 일어남

  • 리페인트 발생 시점
    • a. 리플루우가 발생했을 때
    • b. 요소의 스타일(색상, 배경색 등)이 변경되었을 때
    • c. visibility: hidden ↔ visble로 변경될 때
      • visibility가 변경되는 게 리페인트라면 display: none도 리페인트인건가?
      • 물론 visibility, display: none 둘 다 요소를 화면에서 숨긴다는 면에서 유사하다.
      • 하지만 visibility는 화면에서 공간을 차지하면서 보이지 않는 반면, display: none 는 영역도 차지하지 않으면서 보이지 않게 한다.
      • 영역을 차지하지 않는다는 말을 곧 렌더트리에서 제외된다는 말이므로, display: none이 적용된 요소는 영역이 사라지면서 주변요소의 위치, 크기에도 영향을 주어 리플로우, 리페인트가 발생한다.
      • 하지만 visibility : hidden 이 적용된 요소는 단순히 보이지 않을 뿐, 크기나 위치가 변하는게 아니기 에 리플로우는 발생하지 않고 리페인트만 발생한다.
      • 마찬가지로 color 로 요소의 글자색만 변경했을 때 리페인트만 발생하게 된다.

(리페인트는 요소의 스타일이 변경되었을 때 발생하므로 리플로우보다 비용이 적다.)


리플로우가 발생하면 왜 안좋은가?

리플로우 동안 브라우저는 전체 문서를 탐색하고 페이지에 있는 모든 요소의 위치와 크기를 다시 계산해야 합니다. 이 프로세스는 특히 더 크고 복잡한 페이지에서 계산 비용이 많이 들 수 있습니다. 리플로우는 또한 페이지가 깜박이거나 점프하도록 하여 웹사이트의 성능과 사용자 경험에 부정적인 영향을 미칠 수 있기 때문에 리플로우가 발생하는 상황을 지양해야합니다.

리페인트는 성능에 영향을 미치지 않는가?

리페인트도 성능에 영향을 미치지만 일반적으로 리플로우보다 덜 중요합니다. 리페인트는 색상, 불투명도, 텍스트콘텐츠와 같이 모양의 변경으로 인해 브라우저가 페이지의 요소를 다시 그려야 할 때 발생합니다. 리페인트시 비용이 많이 들 수 있겠지만 일반적으로 리플로우와 동일한 수준의 계산 및 순회가 필요하지 않습니다. 


언제 리플로우가 발생하는가?

  • 페이지 초기 렌더링(최초의 레이아웃 과정)
  • 노드의 추가 혹은 제거(엘리먼트)
  • 요소의 위치 변경
  • 요소의 크기 변경(margin, padding, border, width, height 등)
  • 폰트 변경과 이미지 크기 변경
    • height계산에 영향을 주므로 Global Layout에 영향
  • 윈도우 리사이징
    • 뷰포트 크기가 달라지기 때문에 전체적인 레이아웃을 다시 그려주는 리플로우가 발생.

등등.. 너무나 많은 상황이 있습니다. 특히 인터렉티브한 요소를 위한 제어라면 리플로우를 일으키지 않는다는 것은 사실상 불가능 합니다. 그래서 우리는 비용이드는 리플로우, 리페인트를 줄일 수 있는 여러가지 방법을 생각해봐야 합니다.


성능 최적화(리플로우 리페인트 줄이기)

리플로우와 리페인트는 완전히 피할 수 없습니다. 그러나 최적화할 수 있다면 최대한 줄이는 게 현명한 선택이겠죠! 따라서 우리는 최적화에 대한 고민을 해야 합니다.

Repaint의 경우, Visibility를 DOM API을 통해 조절했을 때 자식 노드들까지 다 검색하기 때문에 성능 저하를 발생시킬 수도 있다고 합니다.

특히 Reflow는 더 심각한 성능 저하를 만들기도 해요. 리플로우는 해당 요소의 자식요소와 부모/조상 요소역시 레이아웃 계산을 진행해버리니까요.

  1. 스타일을 변경할 경우 가장 하위 노드의 클래스를 변경
    • 스타일 변경시 상위노드 전체를 변경하기보다는 그 내부에 있는 하위 노드의 클래스만 변경하게 되면 리플로우가 일어나는 노드의 범위가 더 작아지기 때문에 최적화가 가능합니다, 하지만 이런 방법은 작성되어있는 작성되어있는 구조에서 원하는 스타일을 변경하고자 구조 자체를 변경하기는 어렵기 때문에 실무에서는 적용할 수 있는 범위는 크지 않습니다.
  2. 인라인 스타일을 지양한다.
    • 인라인 스타일은 html을 파싱하는 시점에서 바로 레이아웃에 영향을 미치기때문에 추가적인 리플로우를 발생시킵니다.
  3. 애니메이션이 있는 노드(엘리먼트)는 position 속성을 fixed 또는 absolute로 지정한다.
    • 에니메이션 효과는 계속 변경되기 때문에 많은 리플로우를 발생시키게 되는 포지션을 픽스, 앱솔루트를 하면 애니메이션을 하는 노드를 전체 노드에서 따로 빼서 분리를 시켜버리기 때문에 애니메이션에 해당하는 노드만 리플로우가 발생할 수 있도록 분리 시킬 수 있습니다.
    •  
  4. <table> 레이아웃을 지양한다
    • 테이블 테그는 모두 로드가 되고나서 테이블 너비가 계산된 후 화면에 그려지게 됩니다. 그래서 테이블 콘텐츠의 작은 변경만 있어도 너비를 다시 계산하고 테이블의 모든 노드들이 Reflow가 발생합니다. 이 때문에 <table>을 레이아웃 용도로 사용하는 것은 지양해야합니다.
      • <table> 사용할  table-layout:fixed 값을 지정하는 것이 좋습니다. table-layout:fixed 테이블의 콘텐츠의 길이에 따라 테이블의 너비가 계산되는 것이 아니기 때문에, table-layout 기본 값인 auto 비해 성능이 좋습니다. <table> 레이아웃 용도가 아닌 데이터 표시 용도로 사용할 때도 table-layout:fixed 지정하는 것이 성능 면에서 좋습니다.
  5. CSS표현식을 지양합니다.
    • CSS표현식을 쓰게되면 리플로우가발생 할 때마다 자바스크립트 표현식을 다시 계산하게되고 비용이 높은 코드가 되어버립니다.
  6. CSS 하위선택자 최소화
    • CSS하위 선택자를 최소화 하는것은 Reflow 횟수를 줄이는 방법이 아니라 렌더 트리 계산을 최소화 하는 방법에 대한 내용.
    • CSS 하위 선택자가 많아지면 CSSOM 트리의 깊이(Depth)가 깊어지게 되고 결국 렌더 트리를 만드는 시간이 더 오래 걸릴 수 있게 됩니다. 
      /* 잘못된 예 */
      .reflow_box .reflow_list li .btn{
          display:block;
      }
      /* 올바른 예 */
      .reflow_list .btn {
        display:block;
      }
      <div class="reflow_box">
        <ul class="reflow_list">
          <li>
            <button type="button" class="btn">버튼</button>
          <li>
          <li>
            <button type="button" class="btn">버튼</button>
          <li>
        </ul>
      </div>
  7. display: none 속성을 활용해 스타일 변경하기
    • display: none 가진 노드는 렌더트리가 그려질때 그 노드는 제외가 되기때문에 당장 화면에 보이지 않는 노드라면 display : none 을 활용해서 Reflow 비용을 줄일 수 있습니다.
    • .animation-target {
        position: absolute;
        animation: moveTo 2s;
      }
  8. 캐시를 활용하기
    • 브라우저는 레이아웃 변경을 큐에 저장했다가 한 번에 실행하여 Reflow를 최소화합니다. 하지만 offset, scrollTop과 같은 계산된 스타일 정보를 요청할 때마다 정확한 정보를 제공하기 위해 큐를 비우고 모든 변경사항을 적용합니다.

 


어디서 확인가능한가

  1. 우선 [개발자도구] > [성능] 탭을 연다.
  2. 기록 버튼을 클릭한다.
  3. 기록이 되는 동안, 요소의 글자 색상을 변경한다.
  4. 기록을 중단하고 결과를 보면, 요소의 글자 색상을 변경했을 때 페인트만 발생한 걸 알 수 있다.

https://mong-blog.tistory.com 리플로우, 리페인트와 브라우저 렌더링 알아보기


정리

Reflow는 화면 구조(Layout)이 변경되었을 때, 뷰포트 내에서 렌더 트리의 노드의 정확한 위치와 크기를 계산하는 과정을 Reflow(혹은 Layout)이라고 합니다

Repaint는 화면에 변화가 있을 때 화면을 그리는 과정입니다. 화면의 구조가 변경되었을 때에는 Reflow 과정을 거쳐 화면 구조를 다시 계산한 후 Repaint 과정을 통해 화면을 다시 그립니다.

즉 화면의 구조가 변경되었을 때에는 Reflow와 Repaint 모두 발생합니다.

  • 리플로우와 리페인트는 요소가 시각적으로 변경되었을 때, 변화를 계산하여 화면에 그려주는 작업이다.
  • 만약 DOM이 시각적으로 변경되면 리플로우가 발생하여 렌더트리를 재생성하고,
  • 생성된 렌더트리를 기반으로 요소를 화면에 그리는 리페인트가 발생한다.
  • 화면의 구조가 변경되지 않았는 화면의 변화만 있을 경우 Repaint만 발생한다. 예를들어 opacity, background-color, visiblitiy, outline 등 스타일 변경 시에는 Repaint만 동작한다.

참고

https://lists.w3.org/Archives/Public/public-html-ig-ko/2011Sep/att-0031/Reflow_____________________________Tip.pdf

https://velog.io/@young_pallete/Reflow-Repaint%EC%9D%84-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90#2-repaint-reflow%EB%9E%80

https://mong-blog.tistory.com/entry/%EB%A6%AC%ED%94%8C%EB%A1%9C%EC%9A%B0-%EB%A6%AC%ED%8E%98%EC%9D%B8%ED%8A%B8%EC%99%80-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0

https://beomy.github.io/tech/browser/reflow-repaint/#3-%EC%95%A0%EB%8B%88%EB%A9%94%EC%9D%B4%EC%85%98%EC%9D%B4-%EC%9E%88%EB%8A%94-%EB%85%B8%EB%93%9C%EB%8A%94-position%EC%9D%84-fixed-%EB%98%90%EB%8A%94-absolute%EB%A1%9C-%EC%A7%80%EC%A0%95%ED%95%9C%EB%8B%A4

https://youtu.be/XoyWzOh3Sy4

'프론트엔드 공부 > Web Server' 카테고리의 다른 글

OAuth이란?  (0) 2023.03.09
토큰, JWT(JSON Web Token)  (0) 2023.03.08
Hashing  (0) 2023.03.08
세션(블로깅중)  (0) 2023.03.07
쿠키란 무엇일까? 개념, 필요성, 속성, 문제점  (0) 2023.03.07
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.