본문 바로가기

카테고리 없음

구글 Lighthouse를 이용한 성능개선기

개인 프로젝트 중 성능점수가 낮게 나온 앱이 있어 공부 겸 개선해 보기로 하였습니다.

만든 사이트는 the movieDB API를 이용해 영화정보, 이미지들을 받아 만든 영화 소개 리액트 모바일 웹입니다.

 

 

먼저 성능점수 측정 방법은 개발자 도구 켜고 - Lighthouse탭 - 검사 조건에 맞게 선택하고 - Analyze page load 버튼 클릭

 

 

약간 기다리면 아래와 같이 성능점수와 metrics항목에 각각의 성능지표가 나오는데

제 사이트는 빌드전 개발환경에서 39점, 빌드배포후 깃페이지에서 측정시 47점이었습니다..........

성능개선의 잠재력이 아주 큰 아이지요 허허

metrics 세부항목을 클릭하면 친절한 안내페이지도 있고,

opportunities섹션에 이렇게 수정해라 도움말이 나오는데 하나씩 참고해 나가며 수정해 보았습니다.
LCP, CLS는 구글검색순위에 영향을 주니 특히 신경쓰도록 합시다.

 

1. First Contentful Paint(FCP) : 첫번째 내용물이 화면에 그려지는 시점

2. Largest Contentful Paint(LCP) : 가장 큰 콘텐츠 엘리먼트가 나타날 때

3. Total Blocking Time(TBT) : 총 차단 시간, 페이지가 안정적인 상호 작용 환경이 되기 전, 상호 작용이 불가능했을 때의 시간

4. Cumulative Layout Shift(CLS) : 누적 레이아웃 이동

5. Speed Index

 

 

 

1. 사용자 환경에 맞는 적절한 사이즈의 이미지 제공

이미지 사이즈를 생각안하고 대충 API가이드에 있는 큰 이미지(1080px)를 사용했는데,

LCP항목을 보자마자 아차 싶었습니다.

가로 500px, 1080px사이즈의 이미지가 제공되어 500px기준으로 분기하여 제공하는 것으로 수정.

<picture> 태그는 img 요소의 다중 이미지 리소스(multiple image resources)를 위한 컨테이너를 정의할 때 사용하며,

해상도별, 이미지 포멧별, 레티나디스플레이 고려하여 분기 가능합니다.

 

//as-is
<img src="w1080.jpg" alt="미니언즈2" />

//to-be
<picture className="img">
  <source srcSet="w500.jpg" media="(max-width:500px)" alt="미니언즈2"/>
  <img srcSet="w1080.jpg 2x" src="w1080.jpg" alt="미니언즈2" />
</picture>

 

LCP항목을 개선하려던 작업이었는데 함께 개선된 항목도 있고, 왜인지 CLS항목은 오히려 나빠졌네요.

 

2. 향상된 포멧의 이미지 사용

지원가능한 브라우저에서는 압축률이 좋은 webP, avif포멧의 이미지를  제공할수 있도록 합니다.

  • webP :  png보다 20-30%정도 압축률이 좋음. 유튜브 같은경우 미리보기이미지를 webP로 바꾸어 10%의 성능향상을 얻을수 있었다고 하네요. 꿀뷰 같은걸로도 webP변환이 된다하니, 이미지를 올려 개인 사이트를 만드는 경우 참고. IE미지원  지원 브라우저 현황
  • avif : webP보다 압축률이 더 좋음. IE, edge 미지원  지원브라우저 현황
JPG에서 WebP로 2.96MB 1.10MB 656KB
PNG를 WebP로 4.23MB 2.69MB 482KB
GIF를 WebP로 1.18MB 3.55MB 2.26MB
JPG에서 AVIF로 2.96MB 441KB 324KB
PNG 에서 AVIF 4.23MB 400KB 306KB
GIF 에서 AVIF 1.18MB 235KB 234KB

표참조

<picture>
  <source srcset="example.avif" type="image/avif" />
  <source srcset="example.webp" type="image/webp" />
  <img src="example.png" alt="example file" />
</picture>

 

안타깝게 저는 이미지를 받아오는 TMDB에서 요런 이미지가 완벽히 제공되지 않아 패스했습니다.

 

3. lazy loading사용

초기 로딩에 당장 필요하지 않은 소스나 이미지/iframe 를 늦게 로딩되도록 합니다.

화면아래 컨텐츠나, 툴팁/아코디언 등에 사용된 소스(img, css등)

여러가지 방법의 lazy loading이 있지만 img태그의 loading속성을 이용하였습다.

 

<img loading="lazy" src="" />

 

제 경우 메인이미지 아래 카드형식의 영화목록이 있는데, '더보기'를 눌러야 10개씩 나타나도록 제한되어 있어인지

적용해 보았지만 큰 효과를 나타내진 않았습니다.

 

4. unused CSS 제거

Lighthouse > ctrl + shift + P > show CSS Overview > Unused declaration

하단에 해당 프로젝트에 사용하지 않는 css 목록과 설명까지 나옵니다.

제 경우는 어디서 긁어온 reset.css 하나가 잘못 적용되어 40군데에나 적용이 되어있었네요.....

기본적으로 CSS는 렌더링 차단 리소스로 취급되므로 css는 가볍게 로딩되도록 합니다.

mdn css 성능 최적화

 

5. Layout Shift 항목 관련 수정(자리영역 확보, preload)

웹에 접속해서 페이지를 로드할 때 서버에서 아직 응답을 받지 못한 데이터가 있을 수 있는데,

ui 상으로는 더 하단에 있더라도 더 빨리 렌더링 되는 순서대로 차곡차곡 다른 데이터들이 먼저 자리를 차지하게 되므로, 결국 뒤늦게 도착한 데이터는 정해진 영역에 마치 비집고 들어가는 것처럼 보이게 됩니다.

html 구조상에 위치한 영역에 들어가는 것 뿐인데도 말이지요. 참조

 

이미지 로딩에 시간이 걸리다 보니 css만으로 이루어진 하단 버튼영역이 먼저 나타나고 -> 이미지가 작은 포스터 목록 영역 -> 이미지가 가장 큰 메인이미지 순으로 뒤늦게 로딩이 되었습니다.

 

 

  • 이미지 감싼 태그에 padding-top을 주는 식으로 미리 영역확보를 했고,
  • 랜딩페이지에 데이터를 받아두고 메인이미지, 카드목록을 컴포넌트로 만들어 prop으로 내려주고 있었는데 혹시 이게 시간이 걸리나 싶어서 각 영역을 감싸고 있는 상위태그(레이아웃)만 컴포넌트 밖으로(랜딩페이지) 빼 내었습니다.
    요 프로젝트에는 리덕스를 적용하지 않았는데 스토어를 썼으면 괜찮았을라나 싶네요.
//as-is
<MainImage />
<GridCards />

//to-be
<section className="main_visual">
  <MainImage />
<section>
<ul className="list_cards">
  <GridCards />
</ul>

 

  • 메인이미지 용량이 있다보니 영역이 확보되도 로딩되는 시간이 걸려 preload 이용하여 미리 다운받기로.
    html head태그에 아래 소스 추가. 시각적으로 가장 먼저 보여지는 부분이다보니 확실히 안정적인 느낌이 체감되었습니다.
<link rel="preload" as="image" media="(max-width:500px)" href="https://image.tmdb.org/t/p/w500/1heBUD8o0sgdqLWyeXkylR2POKb.jpg">
<link rel="preload" as="image" media="(min-width:501px)" href="https://image.tmdb.org/t/p/w1280/1heBUD8o0sgdqLWyeXkylR2POKb.jpg">

 

관련수정으로 개선된 CLS점수 변화

 

 

최종 결과

로컬 개발 환경에서 성능점수 39 -> 66

빌드배포후 성능점수 47-> 89

 

 

개인 프로젝트 사이트는 용량이 작아 보통 점수가 좋게 나와서 잘 측정을 안했었는데,

성능점수는 아무래도 이미지 영향이 가장 큰 것 같습니다.

더 수정해 보고픈 것들이 있는데 틈틈히 추가해서 개선해 나가봐야겠네요.