[React] React 프로젝트 성능개선하기 (Cleanup function, CLS 점수 향상)

Brandon·2023년 4월 20일
8

리액트 프로젝트를 마무리하고, 별도로 팀원들과 성능 개선을 위한 코드 리팩토링을 진행하였다.

1. useEffect 안 return 사용

리팩토링 코드 (전후 비교)

이전 코드와 다르게, useEffect 문 안에 사용되는 함수를 return을 통해 반환처리하였다.

Cleanup Function

이처럼 useEffect 훅에서는 함수를 반환 할 수 있는데 이를 cleanup 함수라고 부른다. cleanup 함수는 쉽게 말하자면 useEffect 에 대한 뒷정리를 해주는 역할이다.
useEffect의 두 번째 인자인 의존성 배열이(deps) 비어있는 경우에는 컴포넌트가 사라질 때 cleanup 함수가 호출된다.

이러한 cleanup 함수를 통해

  • 메모리 유출(손실)을 방지할 수 있고,
  • 불필요한 렌더링을 막을 수 있다.

이번 프로젝트 코드에서는

파이어베이스 메서드인 onSnapshot 함수를 통해 userWriteRef 이라는 이름의 firestore cloud 컬렉션에서 데이터를 가져와 map 메서드를 활용하여 뿌려주는 형태이다.
만일 return 을 해주지 않는다면, 컴포넌트가 언마운트 된 후에도 계속해서 userWriteRef를 참조하고 있어 불필요한 렌더링 및 메모리 소요가 발생할 수 있었다.

그래서, 전체 실행 함수 앞쪽에 return을 추가함으로써, 컴포넌트가 언마운트 되고 다음 이펙트가 실행되기전에 정리될 수 있게끔 한다.

cleanup 함수가 자주 쓰이는 Case들

  • 이벤트 리스너
  • 구독
  • 타이머 (ex. setTimeOut , setInterval)
  • 외부 라이브러리 사용 (이번 프로젝트 case)

2. 콘텐츠 레이아웃 이동 최소화

리팩토링 코드

콘텐츠 레이아웃 이동을 최소화 하기 위해 조건부 렌더링되던 부분을 수정하였다.

// 변경 전
{lender ? <Outlet /> : null} 

// 변경 후
 <Outlet />

CLS(Cumulative Layout Shift)

CLS를 그대로 직역하면, 누적되는 레이아웃 변경 이라는 뜻이다. 사용자가 서비스를 이용하는 과정에서 잦은 레이아웃 이동이 피로감을 주고 사용자 경험을 해치는 것을 감안하여, 이러한 레이아웃 이동이 얼마나 콘텐츠 안에서 이뤄지는지를 측정하는 지표로서 통용되고 있다.

높을수록 좋지 못한 점수이며, 일반적으로 0.1을 넘지 않도록 하면 좋은 사용자 환경을 제공한다고 보고 있다.

이번 프로젝트 코드에서는

리액트 라우터의 Outlet 전체를 조건부 렌더링하다보니 상대적으로 false 조건의 null 과의 괴리가 너무 커졌다. 다시 말하자면 화면 전체를 렌더링 하거나 아예 아무것도 보여주지 않거나 하는 조건인데, 실제로는 사용자가 이렇게 아무것도 없는 화면을 볼 확률은 적지만 아무래도 CLS 측정하는 과정에서 이 괴리가 좋지 못한 성능 점수를 야기했던 것 같다.


3. 추가로 진행한 리팩토링

이미지 사이즈 지정

이미지의 사이즈가 지정되지 않은 것도 레이아웃 이동을 유발하여 CLS 점수를 높이는데 영향을 준다고 한다. 그에 따라 이미지들에 widthheight 값을 지정해주었다.

폰트 Preload

사전에 지정된 폰트가, load하는데 있어서 지연 및 로드 실패 등의 이유로 레이아웃 변경 및 이동을 유발할 수 있다. 폰트를 preload를 통해 미리 로드함으로써 레이아웃 변경을 최소화할 수 있다. 앞서 작성한 preload 관련 글에서 자세한 리팩토링 과정을 확인해볼 수 있다.

preload에 대해 알아보자

아래 개념들을 함께 알면 폰트 load의 지연으로 인한 레이아웃 이격이 생기는 것의 원인을 이해하는데 도움이 될 것이다.

  • FOIT (Flash of Invisible Text) : 원래의 글꼴을 불러올 때까지 텍스트 부분을 빈칸으로 두는 메커니즘.
  • FOUT (Flash of Unstyled Text) : 원래의 글꼴을 불러올 때까지 텍스트 부분을 일반(generic) 폰트로 불러와 콘텐츠의 완성을 우선시 하는 메커니즘.

마무리하며...

성능저하를 일으키는 요인들을 포착하여, 성능 점수를 높이는 작업을 진행하였다.
한번 알아두면 어렵지 않은 내용들이니, 다음 프로젝트에서는 처음 코드를 짤 때부터 적용할 수 있도록 해보자.

참고한 글
누적 레이아웃 이동 최적화 (by Addy Osmani)

profile
메인 블로그 이관하였습니다. https://dr-dev.tistory.com/

2개의 댓글

comment-user-thumbnail
2023년 4월 20일

좋은 글 감사합니다. 잘 읽고 갑니다!

1개의 답글