[React Performance Optimization] StatusDisplay

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

StatusDisplay

이번에는 StatusDisplay에 대해 알아보도록 하겠습니다. 제가 구현했던 StatusDisplay는 현 식물공장의 환경상태를 보여주는 컴포넌트입니다.

이 컴포넌트는 어떻게 성능 최적화할 수 있는지 생각해봤습니다. 이 컴포넌트의 특징은 정해진 시간마다 현 상태를 업데이트 해줘야 하는 점입니다. 마운트에 시간을 좀 들이더라도 24시간 켜져있는 스마트팜 대시보드에 컴포넌트 업데이트 시간을 단축시키고자 하는 것이 이번 최적화에 핵심입니다.

RESULT

이 결과는 1초마다 환경상태 데이터를 데이터베이스에서 가져와 업데이트하는 StatusDisplay 컴포넌트를 10초간 지켜보겠습니다. 그냥 지켜보기만 하면 개편 후 컴포넌트는 아무 변화가 없기 때문에 데이터베이스에 새로운 값을 넣어 비교해보겠습니다.

  • 최적화 전 프로파일링
  • 최적화 후 프로파일링

최적화 전 프로파일링은 0.1ms 시간 이하는 모두 제외하였고 최적화 후는 제외 없이 저 커밋 하나 뿐입니다. 두 프로파일링 성능을 비교하고 싶지만 65개의 커밋을 다 계산할 수가 없어 극심한 차이라고 설명드리고 넘어가겠습니다.

HOW

  1. Component Structure
  2. React.memo
  3. Custom Hook (with useSelector)

WHY

1. Component Structure

컴포넌트 구조도 Login 컴포넌트에서 썼든 성능 최적화 방법입니다.

  • Before Component Structure
|___ StatusDisplay
    |___ Figure
    |___ index
  • After Component Structure
|___ StatusDisplay
    |___ Figure
    |___ index
    |___ EnvironmentText

이전 컴포넌트 구조는 useState를 이용해 환경 변수를 만들어 정해진 시간마다 db에 접근해 데이터를 갖고와서 state를 변경해주는 구조였습니다. 정말 비효율적입니다. 결국 바뀌는 건 텍스트 뿐인데 StatusDisplay 컴포넌트 전체를 리렌더링해야합니다. 그래서 이후 컴포넌트 구조는 EnvironmentText 컴포넌트를 따로 만들어 text만 바뀌도록 해주었습니다.

2. React.memo

Login 컴포넌트에서도 봤던 성능 최적화 방법입니다. 이 방법만큼 쉽게 효율적인 방법은 없을 것입니다. 최적화 전 gif에서 커밋이 65개나 되는 이유도 memo를 쓰지 않았기 때문입니다. 새로 들어온 데이터 값이 변해야 업데이트 되는 것이 올바른 방법인데 최적화 전에는 memo를 쓰지 않았기 때문에 다짜고짜 그냥 컴포넌트 전체를 업데이트하고 봅니다.

처음 리액트 공부할 때 memo를 읽어봤지만 기능 구현에는 쓸 일이 없어 보여서 넘어갔다가 이제야 다시 다 고치고 있습니다. 그렇구나 하고 넘기는 것보다 지금 해야 나중에 고생을 안할 수 있습니다. memo에 대한 자세한 설명은 다른 곳들도 많으니 넘어가도록 하겠습니다.

3. Custom Hook (with useSelector)

이전 컴포넌트는 환경 변수를 리덕스에 따로 저장할 필요가 없었습니다. StatusDisplay에서 db에 접근해 직접 가져왔기 때문입니다. 최적화 이후, 데이터 가져오는 부분을 최상위 컴포넌트에 넘겨주고 최상위 컴포넌트가 Redux에 저장하면 useSelector를 이용해 listening 하고 있던 EnvironmentText 컴포넌트는 환경 데이터가 변할 때만 업데이트합니다.

export default function useSubscribeEnvironmentStatus(
  section: string,
  name: string,
) {
  return useSelector((state: RootState) =>
    state[StorageKeys.ENVIRONMENTS][section][name as keyof ReducerEnvironmentDto], shallowEqual
  )
}

위 custom hook을 이용해 redux의 환경 데이터 값을 예의주시하고 있습니다.

Conclusion

최적화 과정에서 useSelector, React.memo를 써야겠다 마음 먹으면 컴포넌트의 구조는 대부분 바뀔 수밖에 없다고 생각합니다. useState를 사용할 때 이거 자식 컴포넌트로 내려서 memo를 이용하면 리렌더링 수를 줄일 수 있을까? Redux 값을 가져오는데 store에 접근해서 그냥 가져오는 것보단 useSelector를 이용해서 변할 때만 가져올 수 없을까? 등등 최적화 방법을 미리 생각하면 구조가 더 빨리 잡힐 것으로 예상됩니다.

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

0개의 댓글