리렌더링 최적화 - 1편

johnyeom
|2025. 1. 26. 13:45
반응형

저는 지금 다니는 회사에 올해 1월에 입사를 했습니다.

입사하기 전, 저만의 목표를 잡았었습니다.

 

바로 저희 서비스의 성능을 개선하기..!! 였습니다.

 

성능을 개선해야 하는 부분은 여러가지가 있었습니다. 

LCP 최적화, 서버 사이드 렌더링으로 인한 일부 페이지 렌더링 속도 저하, 리렌더링 최적화 등이 있었습니다.

 

그 중에 오늘은 리렌더링 최적화 1편으로 찾아왔습니다.

왜 1편이냐면.. 최적화해야하는 부분이 정말 여러곳이 있는데,

 

1편에는 스크롤과 관련된 리렌더링 이슈를 가져왔어요.

 

 

 

 


 

문제 상황

바로 본론으로 들어가보겠습니다.

아래의 영상은 문제 상황을 녹화한 영상인데요.

 

스크롤을 할 때마다, 최상단의 헤더(AppBar 컴포넌트)가 지속적으로 렌더링이 되는 문제가 있었어요.

그리고 더 이상했던 점은 렌더링이 되지도 않는 컴포넌트가 리렌더링이 된다는 점(?)이었어요..!!!

문제 상황

 

저는 우선적으로 위의 두 가지 문제를 해결하고 싶었어요.

 

1. 헤더(AppBar 컴포넌트) 리렌더링 최소화
2. 렌더링이 되지 않는 컴포넌트 리렌더링 방지

 


 

리렌더링이란?

리렌더링(Rendering)이란 React가 UI를 업데이트하기 위해 컴포넌트를 다시 그리는 과정을 의미합니다. 리렌더링은 사용자 경험에 중요한 역할을 하지만, 불필요한 리렌더링은 성능 문제를 일으킬 수 있습니다.

 

예를 들어 볼게요. 카페에서 주문 받는 상황이라고 했보죠!

1. 손님(사용자)이 커피를 주문하면 바리스타(React)가 그 주문을 처리합니다.
2. 바리스타는 손님이 요청한 것만 정확히 준비하면 되지만, 모든 손님의 주문을 다시 확인한다면 불필요한 시간이 소모됩니다.
3. React에서도 필요한 부분만 업데이트하면 되는데, 불필요하게 모든 컴포넌트를 다시 처리하면 성능 저하가 발생합니다.

 

 


리렌더링이 발생하는 상황

리렌더링이 발생하는 주요 이유는 여러가지가 있습니다.

 

위의 상황 같은 경우에는 4번에 해당했습니다.

pages 디렉토리 바로 하위의 Layout.tsx에서 스크롤을 감지하고 화면에 ref가 보이는지 확인 로직이 있었습니다.

 

이는 AppBar 즉 헤더 컴포넌트에 props로 전달되었고,

그로 인해 헤더 컴포넌트는 스크롤을 할 때마다 리렌더링이 되었습니다.

 

1. 상태(State) 변경
   - `useState`나 `useReducer`로 관리하는 상태 값이 변경될 때.

2. Props 변경 
   - 부모 컴포넌트에서 자식 컴포넌트로 전달되는 `props`가 변경될 때.

3. 컨텍스트(Context) 값 변경 
   - `React.createContext`로 생성한 컨텍스트 값이 변경될 때, 해당 컨텍스트를 구독하고 있는 컴포넌트가 리렌더링.

4. 부모 컴포넌트 리렌더링
   - 부모 컴포넌트가 리렌더링되면 자식 컴포넌트도 영향을 받음.

5. 컴포넌트 강제 리렌더링 
   - `forceUpdate`를 호출하거나, `setState`를 동일한 값으로 호출해도 리렌더링이 발생.

6. 의존성 배열 변경  
   - `useEffect`, `useMemo`, `useCallback` 등의 의존성 배열 값이 변경될 때.

7. React.memo 사용 미비
   - 메모이제이션이 적용되지 않아 매번 새로운 객체나 함수가 생성될 때 불필요한 리렌더링 발생.

8. 리덕스나 전역 상태 변경
   - 전역 상태 관리 라이브러리(예: Redux, Zustand 등)의 상태 값이 변경될 때 관련된 컴포넌트가 리렌더링.

9. DOM 이벤트나 외부 요인 
   - 브라우저 리사이즈, 스크롤, 타이머 등과 같은 외부 이벤트로 상태 변화가 발생할 때.

 

 


 

구현결과

저는 그래서 이를 처리하기 위해, Layout.tsx에서 스크롤을 할 때마다

특정 컴포넌트가 보이는지 확인하는 로직을 제거했습니다.

 

AppBar 즉, 헤더 컴포넌트는 더 이상 스크롤할 때마다 리렌더링이 되지 않았고,

헤더의 자식 컴포넌트들도 리렌더링이 되지 않게 되었습니다.

 

구현 결과

 

 

performance 탭에서 스크롤 테스트 결과

결과를 자세히 살펴보면 개선 전에는 9.30s 시간동안 측정을 진행했고, 개선 후에는 9.80s 동안 시간을 측정했는데요!

측정 조건과 환경은 개선 전과 개선 후 모두 동일하게 스크롤을 위아래로 5회 반복했습니다.

 

Scripting시간(JS 코드 파싱, 컴파일링 및 실행, 카비지 컬렉션 포함)을 약 72% 감소시킬 수 있었습니다!!!🔥

rendering, painting, system 모두 약소하게 감소한 것도 확인할 수 있습니다.

 

 

전)

 

개선 전

 

후)

개선 후

 

 

 

 

회사에서 일을 하면서 최적화를 한 경험을 기록할 수 있도록 

열심히 찾고 개선할 것 입니다..!! 😎😎

반응형

'Front-End' 카테고리의 다른 글

리렌더링 최적화 - 2편  (0) 2025.02.17
토스페이먼츠 결제 연동하기  (0) 2025.01.14
[TIL] LCP 최적화 도전하기..!  (0) 2024.10.11
[TIL] 나 혼자 보는 Cypress 기본편  (3) 2024.09.25
웹어셈블리(WebAssembly)란?  (0) 2023.05.21