웹 성능 최적화 #4 성능 측정(프론트엔드)

Explanation

벌써 2024년이 지나 2025년이 되었네요.
모두 모두 새해에도 건강하시고 하시는 일, 좋은 일만 가득하시길 바랍니다! 🙇‍♂️

오늘은 ‘웹 성능 최적화’ 시리즈를 이어서, 웹 서비스의 성능을 측정하는 방법(프론트엔드)에 대해서 간단하게 적어보려합니다. 글에서는 간단한 내용만을 소개하지만 필요에 따라 조금씩 알아가며 활용하면 좋을 것 같아요!

1. 크롬 개발자 도구

1-1. Lighthouse

가장 먼저 간편하고 좋은 접근성으로 웹 서비스의 접근성을 확인할 수 있는 방법으로, 크롬 개발자 도구를 활용할 수 있는데요. 그 중에서 첫번째로 ‘Lighthouse’를 사용하면 아주 편리하게 성능이나 접근성, SEO에 관한 점검과 제안을 받을 수 있습니다.

짜잔! 이전 포스트에서 틈틈이 언급되었던 저의 ‘택배 배송 조회’ 프로젝트는 100점을 받았답니다!
(폭죽이 굉장히 인상적이네요..)

대부분 문제점이나 개선할 부분에 대해서 친절하게 알려주기 때문에 확인하고 수정하면 되지만, 조금 더 알아보자면, Lighthouse 에서는 FCP, LCP, TBT, CLS와 같은 성능 지표를 사용하는데요. 이들을 간략하게 알아보면,

1-1-1. FCP(First Contentful Paint)

페이지가 로드되기 시작해서 사용자가 처음으로 콘텐츠(텍스트, 이미지, 등..)를 볼 수 있게 되는 시점까지 걸린 시간을 측정합니다. 좋은 점수의 기준은 1.8초 이하입니다. 그리고 개선할 수 있는 방법으로는 서버 응답 시간을 단축하거나, 렌더링을 차단하는 리소스(CSS, JS)를 최소화 하거나 콘텐츠의 우선순위를 지정해서 중요한 리소스를 먼저 로드하게 하는 방법 등이 있습니다.

1-1-2. LCP(Largest Contentful Paint)

사용자가 페이지의 주요 콘텐츠를 볼 수 있게 되는 시점을 의미하고 페이지에서 가장 큰 가시 콘텐츠 요소(이미지, 텍스트 블록)가 렌더링된 시점까지 걸린 시간을 측정합니다. 좋은 점수의 기준은 2.5초 이하로, 역시 서버의 응답 시간을 줄이거나 이미지 압축, 폰트 최적화합니다. 그리고 이전 포스트에서 이야기 했던 것처럼 중요한 이미지의 경우 우선 로드(preload)하고 중요하지 않은 이미지는 지연 로드(lazy loading)해서 주요 콘텐츠가 빨리 렌더링 되도록 최적화 할 수 있습니다.

1-1-3. TBT(Total Blocking Time)

FCP와 TTI(Time to Interactive) 사이의 모든 차단 시간의 합 측정으로, 사용자가 페이지와 상호 작용하려 할 때 입력이 지연되는 정도를 나타냅니다. 좋은 점수의 기준은 200ms 이하입니다. 개선 방법으로는 긴 작업(Task)을 필요로 하는 경우 분할하여 동작하도록 해서 메인 스레드의 차단을 최소화 하거나 Web Workers를 사용해서 무거운 작업은 메인 스레드에서 분리할 수 있습니다.

1-1-4. CLS(Cumulative Layout Shift)

페이지 로드 중에 발생하는 모든 레이아웃 이동의 점수 합을 측정합니다. 사용자가 페이지 로드 중에 콘텐츠가 갑작이 이동하면서 발생하는 시각적 안정성을 평가하는 건데요. 좋은 점수 기준은 0.1 이하로, 개선 방법은 이미지나 비디오 요소나 동적으로 로드되는 요소들의 위치에 대한 공간을 미리 예약해 둡니다. 예를 들면 이미지 요소의 width, height 속성을 지정해서 이미지가 로드되기 전에도 해당 공간을 미리 갖고 있어서 레이아웃 이동이 발생하지 않게 하는 것입니다. 그리고 애니메이션이나 전환 효과를 줄 때 효과가 예측 가능한 방식으로 처리되도록 설정합니다.

1-2. Performance

다음으로 성능(Performance) 탭을 통해서 웹 페이지의 성능을 순석할 수 있는데요. 성능 탭을 통해서 페이지 로드 시간, 렌더링 성능, 스크립트 실행 시간, 레이아웃 변경, 애니메이션 등.. 다양한 정보를 확인할 수 있습니다.

이미지를 클릭하면 크게 보실 수 있습니다.

위는 ‘택배 배송 조회’ 서비스의 페이지 로드 부분을 분석한 내용입니다. 간단하게 살펴보면, 네트워크 섹션에서 ‘localhost:2000’ 요청이 2ms 근처에 요청하였고 이후에 브라우저는 index-DqtMhwrY.js(메인 번들 스크립트 파일)과 index-0ENH-..(메인 스타일 시트 파일)에 대한 요청을 보냈네요. 그리고 기본 섹션에서 보면 파란색으로 HTML 파싱을 하고 있는게 보입니다.

네트워크 섹션의 내용을 보면 선으로 된 부분과 박스 부분, 그리고 박스 안에 연한 채색 부분과 진한 채색 부분으로 나뉘어 있는걸 볼 수 있는데요. 여기서 선 부분은 브라우저가 해당 요청이 네트워크 큐에 들어가 리소스 요청하기 전 준비 상태를 의미합니다. 그리고 박스 부분은 실제로 작업 단계를 나타내는데요. 그 안에서 연한 채색 부분은 네트워크 요청을 보낸 후 서버로부터 응답이 도착하기까지의 시간을 의미하고, 진한 채색 부분은 실제로 서버에서 브라우저로 리소스를 다운로드하는 시간을 나타냅니다.

그리고 34ms에 ‘소요 시간’ 섹션에 DCL(DOM Content Loaded – 파란색 박스)로 DOM을 완전히 로드한 것을 확인할 수 있고, 이렇게 DOMContentLoaded 이벤트가 트리거 되는 시점을 알 수 있습니다.

조금 더 확대해서 이후 과정을 살펴보면, ‘택배 배송 조회’ 서비스에서는 두 개의 컴포넌트를 지연 로드 하고 있는데요. 그 부분이 네트워크 섹션에서 48ms, 108ms 부분에 지연 로드된 컴포넌트 스크립트 파일을 호출하고 다운로드 하는 것을 확인할 수 있습니다. 그리고 108ms에 ‘소요 시간’ 섹션을 보면 DOM 트리와 CSSOM 을 결합한 렌더 트리를 구성하고 각 요소의 위치와 크기를 계산하는 레이아웃(빨간색 박스 L) 시점을 알 수 있습니다.

그리고 사용자가 콘텐츠를 시각적으로 볼 수 있게 된 시점인 FP(First Paint), FCP(First Contentful Paint)가 134ms 부분인 것을 알 수 있습니다.

더 시간이 지나고 네트워크 섹션에서 택배사 정보가 로드된 후에는 프레임 섹션과 애니메이션 섹션을 통해서 택배 배송 조회 박스를 포함한 콘텐츠 요소가 애니메이션으로 Fade In되며 출력되는 것까지도 확인할 수 있습니다.

그밖에도 메모리 항목을 체크하여 메모리 사용량을 확인하여 메모리가 지속적으로 증가한다면 메모리 누수를 의심하고 디버깅할 수 있으며, GPU의 활동을 확인하여 GPU를 사용하는 transform과 opacity 속성 들을 활용하여 애니메이션을 최적화하는 등.. 웹 서비스의 최적화를 위한 분석으로 다양하게 활용할 수 있습니다.

2. React DevTools

React를 사용하는 프로젝트라면 React DevTools 확장 프로그램도 애플리케이션의 성능을 분석하고 최적화하는데 유용한 도구인데요. 컴포넌트의 렌더링 빈도나 상태 변경의 영향을 분석하고 불필요한 렌더링을 확인하고 성능을 개선할 수 있습니다.

2-1. Component Tree

Components 탭에서 현재 애플리케이션의 컴포넌트 트리와 각 컴포넌트의 Props, State, Contenxt 값을 실시간으로 확인할 수 있습니다. 이를 통해서 최소한의 Props 흐름을 유지하고 과도한 깊이의 Props는 확인하여 전역 상태 관리 도구를 사용하여 대체할 수 있습니다.

2-2. Highlight Updates

‘Highlight Updates’ 옵션을 활성화하면 업데이트된 컴포넌트를 시각적으로 강조해주는데 이를 활용해서 불필요하게 렌더링 되는 컴포넌트를 쉽게 확인할 수 있습니다.

2-3. Profiler

그리고 위와 같이 Profiler 탭에서는 시간의 순서대로 각 컴포넌트의 렌더링 시간과 호출을 확인할 수 있습니다.

마지막으로 timeline 탭을 통해서 가장 렌더링 비용이 큰 컴포넌트를 빠르게 식별할 수 있고 또 이를 바탕으로 최적화의 우선 순위를 설정할 수도 있습니다. 그리고 그 밖에도 클릭이나 스크롤 등 사용자 이벤트가 렌더링에 미치는 영향을 분석할 수 있습니다.