만족

[React] Tooltip 컴포넌트 퍼포먼스 (withStyles 성능 오버헤드) 본문

[React] Tooltip 컴포넌트 퍼포먼스 (withStyles 성능 오버헤드)

FrontEnd/React Satisfaction 2021. 8. 30. 21:08

한 컴포넌트에 16개의 Tooltip이 포함되어 있고, 그 컴포넌트(ItemCombination)가 10개 존재했을 때 렌더링을 프로파일링한 차트이다.

 

ItemCombination은 장착중인 16개의 아이템을 아이콘으로 표시하고, 각각의 아이콘을 Tooltip으로 감싼 형태이다.

 

코드로 봤을 땐 딱히 성능 저하를 일으킬만한 것이 없어서 왜 느린가 싶었지만,

프로파일링한 결과 material-ui의 컴포넌트들은 withStyle로 감싸져 나가기 때문에

이런 식으로 컴포넌트 내에서 많은 반복을 할 경우 비교적 긴 withStyle의 실행 시간 때문에 성능 저하가 발생한다.

 

실제로 itemCombination에서 Tooltip을 제거하고 빌드했을 땐 렌더링 시간이 압도적으로 빨라졌다는 것을 알 수 있다.

 

필요할 때만 Tooltip 렌더링

위 상황에서는 ItemCombination 컴포넌트 한 개당 16개의 툴팁이 렌더링된다.

 

그러나 툴팁은 어떤 컴포넌트 위에 마우스를 올리면 나타났다가 마우스를 움직이면 사라지므로, 

마우스를 움직이지 않을 때는 딱히 렌더링할 필요가 없다.

 

따라서 다음과 같이 한번 더 래핑해서, 마우스가 올라가 있을 때만 Tooltip을 렌더링하도록 변경했다.

 

const HoverTooltip = ({ tooltip, children }) => {
  const [hover, setHover] = useState(false);

  return (
    <span
      onMouseOver={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
    >
      {hover ? <Tooltip title={tooltip}>{children}</Tooltip> : children}
    </span>
  );
};

별로 특별할 것은 없다.

 

child를 span으로 감싼 후, 그 span에 마우스가 올라가면 Tooltip과 children을 렌더링하고

마우스가 빠져나가면 children만 렌더링한다.

 

실제 퍼포먼스 비교

 

HoverToolTip을 사용했을 때
Tooltip을 전부 렌더링했을 때

당연하게도 처음 컴포넌트가 그려져 있을 때는 호버되지 않았기 때문에

Tooltip이 렌더링되지 않아 Tooltip을 사용하지 않았을 때와 비슷한 수준의 퍼포먼스가 나온다.

 

그렇다면 이제 실제로 hover했을 때 HoverTooltip을 리렌더링이 발생했을 때의 퍼포먼스를 측정해보자.

 

 

이 경우에도 역시 withStyles에서 실행시간이 급격히 올라가는 구간이 분명 존재한다.

 

그러나, 한 번에 16번의 withStyles를 했을 때보다는

마우스를 올렸을 때 딱 한번 리렌더링해서 호출 횟수가 1/16으로 줄었기 때문에

저사양 기기에서도 훨씬 더 안정적으로 UI가 표시된다.

 

withStyle은 무슨 역할을 할까

일단 with라는 prefix가 있는 것으로 보아 hoc인 것을 유추해볼 수 있다.

 

실제 코드를 열어보면, 꽤 복잡한 형태를 띄고 있다.

 

https://github.com/mui-org/material-ui/blob/c87d71827fbcddf24335e6df21d785bf19319e57/packages/material-ui-styles/src/withStyles/withStyles.js#L12

 

GitHub - mui-org/material-ui: Material-UI is a simple and customizable component library to build faster, beautiful, and more ac

Material-UI is a simple and customizable component library to build faster, beautiful, and more accessible React applications. Follow your own design system, or start with Material Design. - GitHub...

github.com

withStyle은 context로부터 내려받은  theme나, 기본 스타일, 커스텀 스타일 등을 option으로 받아 뭉친 후

만들어진 style을 hoc패턴을 이용해 전달받은 컴포넌트에 지정한다.

 

이 과정이 꽤나 무거운지, 하나만 렌더링했을 때에도 마찬가지로 대부분의 시간을 withStyles가 잡아먹는다.

 

깃헙 이슈에도 올라왔던 주제인데, 근본적인 해결은 불가능한 모양이다.

 

아무튼 Tooltip 처럼 반복하지 않아도 되는 withStyle-component들은 최대한 반복하지 않는 편이 좋겠다.



Comments