안녕하세요, 흔한 감자입니다.
이번 블로깅에서는 현재 개발 진행중인 이모주모 (독서 토론 웹서비스) 사이트에서 찬반 토론에 사용되는 ProgressBar의 성능 개선한 경험을 기록해보려고 합니다.
width가 변경됨에 따른 Reflow가 발생
하여 성능 저하가 발생함(버벅이현상이 발생)ProgressBar를 이야기하기에 앞서 알아야할 사전 지식있습니다. 바로 Reflow
와 Repaint
인데요. 그럼 관련 용어들에 대해 우선 알아볼까요?
알아야하는 기본 용어들에 살펴봤으니 기존 소스를 살펴보겠습니다.
...
function ProgressBar({
isDisplayContent = true,
barWidth = '100%',
barHeight = '100px',
value = '50',
size = 'sm',
}: IProps) {
return (
<Container barWidth={barWidth}>
<BarContainer barHeight={barHeight}>
<Bar value={value} />
</BarContainer>
{isDisplayContent && (
<ContentContainer>
<Content size={size} pos="left">
찬성 {value}%
</Content>
<Content size={size} pos="right">
반대 {100 - Number(value)}%
</Content>
</ContentContainer>
)}
</Container>
);
}
...
const Bar = styled.span<{ value: string }>`
position: absolute;
left: 0;
top: 0;
height: 100%;
transition: width 0.4s ease;
width: ${({ value }) => value}%;
background-color: var(--color-primary-mint);
`;
...
export default ProgressBar;
width
의 %
로 계산하고 애니메이션 transition
에도 width
사용하고 있음.width가 변경됨에 따른 Reflow가 발생
하여 성능 저하가 발생함(버벅이현상이 발생)Reflow 없애는 가장 일반적인 방법은 바로 transform
과 opacity
속성을 이용하는 것입니다. 이 속성들을 이용하면 레이어가 분리처리되어 Layout
과 Paint
가 일어나지 않고 composition
만 일어나기 때문에 부드럽게 처리가 가능합니다. (즉, Reflow가 발생하지 않음)
또한, GPU 가속
도 이루어지기 때문에 속도도 개선시키는 효과도 볼 수 있습니다.
const Bar = styled.span<{ value: string }>`
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
transform: scaleX(${({ value }) => Number(value) / 100});
transform-origin: left;
transition: transform 0.4s ease;
background-color: var(--color-primary-mint);
`;
width: 100%;
로 고정시키고 찬성 반대 비율을 transform을 이용하여 표시하도록 수정하였습니다.최근 성능 최적화에 관심이 많아 인프런의 프론트엔드 개발자를 위한, 실전 웹 성능 최적화(feat. React) - Part. 1 강의에서 여러 최적화 방법을 공부하던 중 애니메이션 최적화 내용이 우리 프로젝트에도 적용하면 좋겠다는 생각에 개선시키는 작업을 진행해 보았습니다.
개선된 부분이 사실 미세한 차이라 CPU 감속 옵션을 키지 않는 이상 차이점을 느끼기에는 어려웠지만, 이런 부분이 쌓이다 보면 사용자 경험을 떨어뜨리기 때문에 유의미한 개선이었다고 생각됩니다.