현재 다니고 있는 회사에서는 reflow
와 repaint
까지 신경 쓸 정도로 퍼포먼스를 기대하지 않아서 당장 실무에서 적용할 일이 크게 없지만, 추후에 다른 환경에서 개발한다면 필요하지 않을까 하는 생각에 정리해봅니다.
reflow
와 repaint
를 잘 이해하고 관리한다면 성능최적화에 큰 도움이 됩니다.
먼저 브라우저 렌더링 과정을 먼저 이해하면 좋을 것 같습니다.
1. HTML 파싱
브라우저는 HTML 문서를 받아서 읽고 DOM(Document Object Model) 트리를 생성합니다.
2. CSS 처리
모든 CSS를 파싱하고 CSSOM(CSS Object Model) 트리를 생성합니다.
3. 렌더 트리 생성
DOM과 CSSOM을 결합하여 렌더 트리를 생성합니다. 실제로 화면에 렌더링될 요소들만 포함됩니다.
4. 레이아웃 계산
요소들의 정확한 위치와 크기를 계산합니다. viewport 내에서 요소들의 정확한 위치를 결정합니다.
이 과정을 리플로우(reflow
)라고도 부릅니다.
5. 페인트
렌더 트리의 각 노드를 실제 픽셀로 변환하고 색상, 테두리, 그림자 등 모든 시각적 스타일을 그립니다.
6. 컴포지션
페인트된 레이어들을 최종적으로 합성하여 최종 이미지를 만들어 화면에 표시합니다.
reflow
는 브라우저가 페이지의 레이아웃을 다시 계산하는 과정입니다.
DOM 요소의 기하학적 속성(크기, 위치, 레이아웃)이나 CSS 스타일이 변경되면 브라우저는 각 요소가 화면에 어떻게 배치될지 다시 계산해야 합니다. 이 과정은 모든 자식 요소와 관련된 부모 요소까지 영향을 주기 때문에 비용이 매우 높은 작업입니다.
reflow
를 주로 발생시키는 작업은 다음과 같습니다.
DOM 요소 추가/삭제
요소의 크기 변경 (width
, height
)
위치 변경 (margin
, padding
)
브라우저 창 크기 조정
폰트 변경
텍스트 내용 변경
CSS 속성 중 레이아웃에 영향을 주는 속성 변경 (display
, position
)
위 작업들은 개발하면서 자주 사용하는 작업이고 모두 reflow
를 발생시킵니다.
repaint
는 요소의 외관이 변경되지만 레이아웃에는 영향을 주지 않을 때 발생합니다. 요소의 시각적 스타일(색상, 배경)만 다시 그리는 과정으로 브라우저는 요소의 모양만 다시 그리면 되기 때문에 reflow
보다는 연산 비용이 상대적으로 낮습니다.
하지만 여전히 성능에는 영향을 줄 수 있습니다.
repaint
를 주로 발생시키는 작업은 다음과 같습니다.
background-color
변경
color
변경
visibility
변경
box-shadow
변경
outline
변경
위 작업들은 개발하면서 자주 사용되는 작업이고 모두 repaint
를 발생시킵니다.
reflow
와 repaint
를 잘 관리한다면 성능 최적화에 도움이 됩니다. 아래와 같은 방법들로 최적화할 수 있습니다.
reflow
를 발생시키는 CSS 속성 사용을 최소화
width
, height
, margin
, padding
, border
등의 속성은 요소의 레이아웃을 다시 계산하게 하므로 reflow
를 일으킵니다. 가능한 미리 CSS에서 스타일을 설정해 초기 로드 시에만 계산이 이루어지도록 하고 이후에는 변경하지 않는 것이 좋습니다.
CSS 애니메이션 최적화
애니메이션에서 transform
과 opacity
속성만을 사용합니다. 이 두 속성은 GPU 가속을 사용할 수 있어 reflow
를 일으키지 않고 repaint
만 발생시키므로 CPU 자원을 적게 사용할 수 있습니다.
will-change 속성 사용
CSS의 will-change
속성을 사용하여 브라우저에 특정 요소가 변경될 것이라고 미리 알려줄 수 있습니다. 예를 들어 will-change:transform
으로 미리 GPU에서 요소를 준비하게 하여 reflow
및 repaint
에 미치는 영향을 줄일 수 있습니다. 하지만, will-change
속성은 너무 자주 사용하면 메모리 낭비가 발생하므로 필요한 요소에만 적용해야 합니다.
Batch Update 하기
DOM 업데이트를 하나로 묶어서 Batch update 한다면, reflow
를 최소화할 수 있습니다. 예를 들어 DocumentFragment를
활용해 다수의 DOM 조작 이후 마지막에 한번만 반영한다면 reflow
를 가능한 적게 발생시킬 수 있습니다.