[React Performance Optimization] SwitchController

김병진·2021년 3월 26일
0
post-thumbnail

SwitchController

이번에는 스마트팜 원격 조종에 필요한 스위치를 최적화한 경험을 공유하려 합니다. 스위치의 작동은 아래와 같습니다.

gif 만드는 프로그램이 제 사이트 인식을 잘 못하는 것 같습니다. 3번째 스위치가 on / off 되고 있는 것을 보여드리려 했습니다..

여기서 중요한 점은 스위치를 작동시키면 아래의 gif와 같이 스위치 기록 컴포넌트가 업데이트되면서 기록을 보여줍니다.

RESULT

테스트 과정은 위의 gif와 같이 스위치 상태를 바꾸는 작업입니다.

  • 최적화 전 프로파일링

  • 최적화 후 프로파일링

위 두 프로파일링은 0.1ms 시간 이하는 모두 제외하였습니다. 두 프로파일링 성능을 아래의 표를 이용해 비교해보도록 하겠습니다.

BeforeAfterComp.
Commits13 steps2 stepsx0.15
Largest Time14.3ms3.5msx4.08

제가 생각한 커밋이 딱 2개로 나왔습니다. 스위치가 작동되고 스위치 기록에 기록이 추가되는 과정이 딱 두 가지입니다.

그리고 커밋은 0.15배로 줄었으며 가장 오랜 시간 렌더링한 커밋은 4배나 차이가 납니다.

HOW

  1. The Way How to Fetch Data
  2. Custom Hook (with useRef)
  3. CSS styles

WHY

  1. The Way How to Fetch Data

스위치가 바뀜에 따라 useSelector를 이용해 리스닝하고 있던 스위치 기록 컴포넌트가 데이터를 업데이트하는 것이 기본 과정입니다. 여기서 최적화한 부분은 어떻게 데이터를 업데이트하는가 입니다.

최적화 전에는 useSelector를 트리거 신호로 사용해 데이터베이스에 접근해서 데이터를 가져왔습니다. 그러다보니 또 useState를 사용하게 되고 리렌더링을 피할 수 없게 됩니다.

그래서 생각해낸 것이 useRef입니다. 즉, 데이터베이스에서 스위치 변경 데이터를 가져오던 방식에서 Redux를 통해 단 한 번의 렌더링으로 해결가능합니다. useRef에 대한 설명은 다른 자료들도 많으니 넘어가고 어떻게 사용했는지 2번에서 설명드리겠습니다.

  1. Custom Hook (with useRef)

usePrevious라는 hook을 이용했습니다. 구글링해도 나오는 유명한 custom hook입니다. 보통 리렌더링하게 되면 값이 초기화되고 리렌더링 전에 연산 작업을 거친 데이터는 사라집니다.

이 때 필요한 hook이 usePrevious입니다. 리렌더링되어도 저장한 값을 가지고 있습니다. 아래의 코드를 통해 구현됩니다.

export function usePrevious<T>(value: T): T | undefined {
  const ref = useRef<T>();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
}

저는 이 hook을 이용하여 useSelector의 리턴값(현재 스위치에 대한 redux 값)과 이전 값을 비교하여 바뀐 데이터를 찾아내 기록에 추가해주었습니다.


3. CSS styles

이번에 프로파일링을 게속 보다보니 withStyles 렌더링 시간이 개편 전보다 개편 후에 더 많이 나온다는 것을 깨달았습니다.

유일한 차이는 확장자입니다. 개편 전에는 컴포넌트 파일 안에서 material-ui의 useStyles와 makeStyles를 이용했으나 이후 scss로 따로 떼내어 관리했습니다. 아마 webpack 모듈 번들러를 거쳐 컴파일하다 보니 시간이 더 걸리는게 아닌가 싶습니다.

CONCLUSION

useRef와 데이터를 가져오는 방식의 최적화를 통해 이번에 최적화를 진행해보았습니다. 다음 번에는 또 다른 컴포넌트를 이용하여 최적화를 진행해보도록 하겠습니다.

profile
아이디어를 구현할 수 있는 개발자가 목표입니다.

0개의 댓글