음악, 삶, 개발

조건부 랜더링보다는 CSS className 이 훨씬 빠르다. 본문

개발 Web/React

조건부 랜더링보다는 CSS className 이 훨씬 빠르다.

Lee_____ 2021. 7. 6. 07:15

지난 1주일동안 React app 의 성능 향상을 위해 많은 자료를 찾아보고, 직접 실험도 이것저것 해보았다.

사실 음악 관련 GUI 를 리액트로 개발한 선례를 찾아보기가 힘들었기에, 스스로 파헤쳐내야 하는것도 꽤나 많았다.

일반 앱들과 음악앱이 다른점은, 음악앱에서는 UI 의 레이아웃 전환이 매우 빠르게, 매우 자주 발생한다는것이다.

Ableton 을 생각해보면 수많은 UI 버튼, 슬라이더, 믹서 노브등이 떠 있는 상태에서, tab 키를 누르면 곧바로 다른 레이아웃으로 전환된다.

이 레이아웃 전환시 30ms 이상이 되면 사용자도 충분히 인지할수있으며, "어 조금 느린데? 왜 이러지?" 라면서 나에게 이메일을 보내게될수있다.

음악을 하는 사람들은 작은 타이밍의 차이도 매우 예민하게 잘 느낄수있기때문이다.

 

본론으로 들어가서, React 에는 조건부 랜더링이 있다.

조건에 따라 서로 다른 Component 를 return 하는것인데, 이게 해당 Component 의 node 가 매우 적으면 별 문제가 안될수있지만,

만약 거대한 Component 가 조건에 따라 빠르게 return 되야하는 상황이라면 이것은 매우 느렸다.(30~50ms)

unmount 와 mount 가 반복적으로 되면서, "어 느린데?" 라는걸 느끼게해준것이다.

 

당연히 css className 을 조건부로 변경하는것보다는 코드의 가독성으로도 당연히 조건부 랜더링을 해야한다고 생각했지만,

현실은 그렇게 호락호락하지않았고, className 변경이 조건에 따른 Component 를 return 하는것보다 압도적으로 빨랐다.

React.memo 와 className 변경을 결합해서 사용했을때, 매우 거대한 component 의 전환도 30ms -> 2ms 로 줄일수있었다.

 

여기서 중요한것은, 내가 런타임에서 사용하게 될 컴포넌트들을 미리 로딩해놓는것이다.

애초에 모든것을 로딩하고 그리고 이것들을 절대 unmount 하지않고, display: "none" 또는 visibility: visible 같은 css 속성을 통해 보이고 숨기고하는것이다.

 

stackoverflow, reddit 등을 뒤지면서 모두가 조건부랜더링을 말하는데, 

결과적으로 음악앱에는 사용할수없는 스킬이라는 결론을 내렸다.

 

사실 나도 아직 모든걸 전혀 알고있지못하며, 경험상으로 생각난것들을 한번 정리해보았다.

이 글의 결론은 추후 당연히 변경될수있다. (새로운 최적화 방법을 찾는다면)

 

css className 과 씨름하는것은 매우 tedious 하지만 성능을 위해서는 어쩔수없다.

또한 inline style 즉, react 에서 style 속성을 통해 css 를 변경하는것은 최대한 피해야한다.

 

그리고 런타임 환경에서 dom 삽입과 삭제가 매우 자주 일어날것이라 예상된다면,

dom 을 사용하는대신에

귀찮더라도 <canvas/> 를 무조건적으로 사용해야한다. (note 를 추가하거나 삭제하거나 등등)

 

사용의 우선 순위를 정리해보면 다음과 같다.

 

1. css className

2. className 으로 해결할수없는 미묘한 값의 변화가 발생한다면 그제서야 style 

3. 하지만 요소가 매우 많다면 <canvas />

4. 이 모든것이 안되면 조건부 랜러딩