🧑🏻🎨 성능 개선의 핵심 Repaint, Reflow
- 브라우저 렌더링 단계에서 사이트 최적화는 html parser, css parser, layout, painting 에서 이루어지며, 브라우저 렌더링 성능을 결정하는 중요한 요소 중 하나는 메인 스레드 점유 여부이다.
- 적용하는 CSS속성에 따라 렌더링 파이프라인에서 다시 진행해야 하는 시작점이 다르고, Reflow -> Repaint -> Composite 순으로 렌더링에 대한 비용이 낮다. (하지만 과도한 레이어 사용은 오히려 레이어 합성의 오버헤드로 인해 병목이 생길 수 있다.)
- 👉🏻 때문에 reflow와 repaint는 사이트 최적화에서 가장 큰 핵심으로 최소화하는 것이 중요
Reflow
자바스크립트로 요소의 크기를 변화시킬 경우 레이아웃 계산 및 이후 단계를 모두 수행해야하며, 스타일과 레이아웃 이후 단계가 모두 재실행되는 것을 reflow라고 한다.
Repaint
background-color를 변경한 경우는 스타일은 재계산해야 하지만, 요소의 위치에 영향을 주지 않는 속성이기 때문에 레이아웃 단계를 건너뛰고 Paint부터 수행된다. 이렇게 Paint이후 단계부터 재실행 되는 것을 repaint라고 한다.
Composition only
합성이란, '페이지가 어떻게 보여야 하는지에 대한 정보를 픽셀로 변환한 다음 Compositor Frame을 생성하는 과정'이다. transform, opacity속성을 사용하는 애니메이션은 메인 스레드 개입 없이, 복사된(Commit)레이어를 사용해서 렌더링하므로 빠르다.
🌳 DOM Tree 최적화
- html 태그는 원래 용도대로 사용
- 👉🏻 최근 리액트를 사용하면서 기본적인 html태그사용을 지키지 않는 경우가 있는데, 구조나 태그 용도의 기존 규칙만 잘 지켜줘도 접근성과 최적화는 가져갈 수 있다.)
- HTML 구조를 깊게 짜지 않는다.
- 👉🏻 DOM트리가 길어진다는 건 브라우저에서 확인해야할 단계가 많아진다는 것을 의미함
💅🏻 Style 계산 최적화
Repaint 발생 속성을 사용한 애니메이션
const backgroundAnimation = keyframes({
'0%': { backgroundPosition: '0% 50%' },
'50%': { backgroundPosition: '80% 100%' },
'100%': { backgroundPosition: '0% 50%' },
});
const Main = styled('main', {
// ...
'&::before': {
position: 'absolute',
animation: `${backgroundAnimation} infinite 20s linear`,
}
})
background-position변경으로 repaint가 지속발생하여 CPU사용량이 높음
Composition만 발생하는 속성을 사용한 애니메이션
const backgroundAnimation = keyframes({
'0%': { transform: 'translateX(-50%) rotate(0deg)' },
'50%': { transform: 'translateX(-50%) rotate(270deg)' },
'100%': { transform: 'translateX(-50%) rotate(0deg)' },
});
const Main = styled('main', {
// ...
'&::before': {
position: 'absolute',
animation: `${backgroundAnimation} infinite 20s linear`,
}
})
transform속성을 사용하는 애니메이션은 메인 스레드 점유 없이 복사된 레이어를 사용하므로 repaint없이 합성만 발생하기에 훨씬 부드럽게 처리 가능
정리
- CSS는 규칙을 너무 복잡하게 하지 않고, 셀렉터를 짧게 사용한다.
- 👉🏻 selector가 늘어남에 따라 브라우저에서 연산할 일이 많아짐
- 인라인 스타일을 사용하지 않는다.
- 👉🏻 DOM, CSSOM트리를 다 만들어 놓고, Render트리에서 확인할 때 css에서 확인했던 걸 다시 html에서 확인하면서 왔다갔다 하는 과정이 생긴다.
- 렌더트리 생성 이후 박스 모델을 변경하지 않는다.
- 애니메이션이 있는 요소는 position:fixed|absolute, trasform, opacity를 사용하고 will-change를 지정한다.
- position:fixed|absolute는 전체 레이아웃 흐름을 방해하지 않고 위에 떠있는 요소이기 때문에 전체 페이지의 reflow가 일어나지 않음
- transform, opacity속성을 사용하는 애니메이션은 메인 스레드 개입 없이 GPU에서 계산하기에 성능에 유리함
- will-change를 사용하면 움직임이 있을 것이라는걸 브라우저가 해당 속성이 변하는 것에 준비를 할 수 있다.
- js로 스타일을 변경할 때는 display:none으로 숨긴후 변경, 노출한다.
- 👉🏻 바꿀걸 다 바꾸고 마지막에 한번에 보여주는 게 낫다.
- css 속성별 렌더트리 발생 확인 사이트
- https://www.lmame-geek.com/css-triggers/
이미지 최적화
- 반드시 이미지는 최적화 과정을 거칠 것
- 이미지 파일을 주고 받는 횟수도 줄여주는 것이 중요함
- 아이콘 이미지 10개보다 아이콘을 모아둔 이미지 1개의 용량이 작음 👉🏽 이미지 스파라이트(image sprite)기법
참조