본문 바로가기
공부/FE

[웹 기본 쌓기] 렌더링, 리플로우/리페인트

by Piva 2024. 1. 10.

근래 이런저런 자료를 접하며 부족했던 기본 지식을 쌓고 있다.

  • 특히 개발할 때 MDN 문서를 자주 참고하며 도움을 얻는 편이었는데, 이 MDN에 좋은 문서들이 많아 시간 날 때 조금씩 읽는 중.
  • 이미 문서로 나와있는 내용이지만 블로그에 남기며 한 번 더 복습을 하게 되므로... 읽은 것을 백업 겸 가볍게 끄적인 내용을 적는다.

렌더링은 어떻게 될까? (중요 렌더링 경로, Critical Rendering Path)

중요 렌더링 경로

: 렌더링 과정을 일컫는 말(정확히는, 브라우저가 HTML, CSS, JS를 화면상의 픽셀로 변환하는 단계).

브라우저는 요청을 통해 웹페이지에 대한 정보를 받아서 아래와 같은 과정을 거친다.

 

1. HTML을 분석한다(이때 분석을 파싱이라고 함). 분석한 HTML을 가지고 DOM 트리(Document Object Model)를 만든다.

2. CSS를 분석한다. 역시나 분석을 통해 CSSOM (CSS Object Model)을 구축한다.

※ CSSOM: 브라우저는 CSSOM의 구축이 완료될 때까지(== 모든 CSS가 처리될 때까지) 컨텐츠의 렌더링을 막는다.
→ CSS (Cascade)는 종속적인 특징을 갖고 있어, 하위 요소가 상위의 스타일을 상속할 수 있음. 또한 앞서 나온 규칙이 후에 나올 규칙에 의해 덮여쓰여질 가능성이 있음. 그렇기 때문에 CSS가 완전히 분석되기 전까지 렌더링이 되지 않는 듯...

 

3. DOM과 CSSOM의 생성이 완료되면 렌더 트리를 만든다. 또한 스타일/위치/크기를 계산한다.

※ 렌더 트리(Render/Rendering tree): 페이지 렌더링 시 필요한 컨텐츠만을 갖는 트리. 즉, 화면 상에서 보여지지 않는 요소들(ex. script 태그)은 렌더 트리에 포함되지 않는다.

 

4. 렌더트리의 생성되면, 모든 요소들의 위치와 크기가 계산된 레이아웃(Layout)이 만들어진다.

5. 레이아웃이 완료되면 페이지가 렌더링(혹은 '그려진다' === Paint)된다.

 

 

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

리플로우(Reflow)

: 브라우저가 웹페이지 위치 및 기하학적 구조를 다시 계산할 때 발생하는 것. 다시 말해 DOM 트리의 요소들에 '레이아웃에 변화를 주는' 변경이 일어났을 때 발생한다.

→ 한 요소에 reflow가 일어나면 그 요소에 속한 하위 요소들에게도 reflow가 일어난다.

 

리페인트(Repaint)

: 시각적인 업데이트를 위해 브라우저가 웹페이지를 다시 그릴 때 발생하는 것. 여기서 '시각적인 업데이트'란 어떤 요소의 가시성에 변화가 일어났음(단, 레이아웃에 영향을 끼치진 않았을 때)을 말한다. (ex. background-color, opacity 등...)

→ 대체로 리플로우가 일어나면 그 후에 리페인트가 일어난다.

리플로우와 리페인트는 성능적으로 큰 영향을 끼치는 작업이다. 특히 reflow는 모바일 환경과 같이, 처리 능력이 낮은 기기에서 큰 성능저하를 일으킬 수 있다.

 

 

언제 reflow와 repaint가 일어날까?

  위 블로그 글의 몇 가지 예시로 차이를 이해할 수 있었음.

  • visibility 속성이 hidden으로 바뀌었을 때: repaint만 일어난다. hidden인 요소는 보이지만 않고 DOM 트리에서 제거되진 않기 때문.
  • display 속성이 none으로 바뀌었을 때: 둘 다 일어난다. reflow가 일어나는 이유는, none 속성으로 바뀜에 따라 요소가 DOM 트리에서 제거되기 때문(레이아웃에 변경이 생길 것이다).
  • DOM 노드를 움직이거나 애니메이션을 적용할 경우: 둘 다 일어난다. 움직이거나 애니메이션을 주는 것은 레이아웃에 변화를 주는 작업이니까...
  • 윈도우의 크기를 바꾸는 경우: reflow가 일어난다. 요소들의 가시성(외형적인 부분)에는 변화 없이 요소들의 크기 변화가 일어나서.

 

reflow와 repaint 줄이는 방법

→ 앞서 언급했듯 두 작업은 성능에 영향을 미치는 영역. 따라서 이 두 가지가 일어나는 것을 줄이면 성능 개선에 기여할 수 있음.

  1. 스타일을 하나하나 바꾸지 말기. (한 번 바꿀 때마다 repaint가 일어날 것이다)
  2. 바뀌는 스타일을 매번 계산하기 보다, 저장해두고 그 값 가져다 쓰기.
  3. DOM 변경을 일괄적으로 처리하기
    - 100개의 변경점이 존재한다고 할 때, 이를 하나하나 변경하면 수많은 reflow/repaint가 일어날 수 있다.
    - 변경할 요소를 none으로 잠시 숨기고, 숨긴 상태에서 100개의 변경점을 반영한 후 다시 보이게 하면 훨씬 적은 reflow/repaint로 작업을 완료할 수 있다.