본문 바로가기

Web Development/Problem Solving

[Web] Light house를 이용한 페이지 최적화

Light house의 성능 지표 분석 결과

  • First Contentful Paint (FCP): 1.9초
    사용자가 처음으로 페이지의 콘텐츠를 볼 수 있는 시간. 50~89 사이이므로 평범
  • Largest Contentful Paint (LCP): 17.6초
    Lighthouse, Google의 웹 성능 지표에 따르면, LCP의 적정 시간은 2.5초 이하 : 우수, 2.5 ~ 4 : 개선 필요, 4 ~ : 성능 저조 이다. 2.5초 이하로 LCP를 떨어뜨려야 한다.

    LCP는 페이지의 주요 콘텐츠가 완전히 렌더링되는 시간이다. 여기서 말하는 주요 콘텐츠는 아래와 같다.
    - 이미지 요소(<img>태그)
    - 비디오 포스터 이미지(<video>태그의poster속성)
    - 백그라운드 이미지(CSSbackground-image속성)
    - 텍스트 블록 (<div>, <p>, <h1> 등의 블록 레벨 텍스트 요소)
    LCP는 전체 콘텐츠가 아니라 사용자가 처음에 볼 수 있는 “가장 큰 콘텐츠”가 렌더링 되는 시간을 측정한다.
    모든 이미지, 비디오가 로드되는 시간이 아니라, 주요 콘텐츠가 표시되는 시간을 기준으로 한다.ㅁ

    내 페이지에서 LCP가 길었던 원인은 아래와 같다.
    - TTFB : 610ms
      서버가 첫 번째 바이트를 클라이언트에게 보내는 데 걸리는 시간. 서버 응답 시간이 460ms로 상대적으로 빠른 편.
    - 로드 지연 14,250m
       로드 지연 (Load Delay)은 이미지가 로드되기 전까지의 시간. 즉, 이미지 요청이 시작되고 나서 실제 로드가 시작되기까지 걸리는 시간
    - 로드 시간 : 0ms
       이미지가 실제로 로드된 시간
    - 렌더링 지연 : 380ms
       이미지가 렌더링되는 데 걸리는 시간
    종합해보면, 이미지가 로드되는 시간 자체가 긴 것이 아니라, 로드 되기 전 다른 리소스들이 로드 되는 시간 때문에, 이미지 로드가 지연되어 생기는 문제라는 것이다.

lighthouse 측정 결과

네트워크 탭을 확인해보니 크게 3가지 문제를 발견할 수 있었다.

  1. 페이지 내 모든 이미지를 첫 로드 시, 가져오고 있음.
  2. react 번들 파일의 크기 1.1MB
    권장 크기 : 최대 250KB (gzip 압축 후) 권장 크기에 비해 매우 큰 수치이기 때문에, 번들 크기 최적화가 초기 로드 시간을 줄이는데 영향을 미칠 것으로 판단했다. 초기 로드 시간 또한 lighthouse 기준 1.9초로 1초 이하가 이상적인 초기 로드 시간이기 때문에 최대한 줄여보기로 했다.
  3. 홈에서 사용하는 데이터를 가져오는 api 응답 속도 1.06초
    홈에서 필요한 데이터(렌더링할 이미지 경로 등)을 받아온 다음 이미지 다운로드 및 페이지 렌더링을 하게 되기 때문에 그 전까지 많은 시간이 걸리는 것이었다.

번들 크기 1.1MB

 

main api 응답 속도 1.06초



위 3가지 문제를 각각 해결해보기로 했다.

  1. 이미지 lazy load 적용
    총 로드 시간이 1초, DOMContentLoaded 시간이 0.5초 정도 단축되었다. 이 단축은 로컬 환경에서 줄어든 속도이다.(로컬 환경의 경우, 제한된 데이터를 가지고 있음) 실제 운영 환경에서는 페이지 내 이미지가 3배 정도 많기 때문에 더 효율이 좋을 것이라고 생각한다.

운영 서버 네트워크 탭, 로드 시간 : 1.49초
lazy load 적용 후

 

2. react 번들 파일 크기 최적화

- lodash.js 라이브러리 최적화
lodash.js 라이브러리가 큰 부분을 차지하고 있어서, 사용하는 부분만 선택적으로 import 해주었다. 이를 위해 lodash-es 라이브러리를 사용했다. 그러나 큰 효과를 보지는 못했다. 번들사이즈 : 1.06mb → 1.05mb

<lodash.js 패키지 정리 전> bundle size : 1.06MB>
<lodash.js 패키지 정리 후> bundle size : 1.05MB

- 코드 스플리팅
코드 스플리팅을 통해 번들 사이즈를 줄여보았다. Home을 제외한 모든 페이지 컴포넌트에 lazy로드를 적용했다.

 

3. 홈에서 사용하는 데이터를 가져오는 api 응답 속도 줄이기
이 문제를 해결하기 위해서는 백엔드 api 코드를 고쳐야 한다. 현재 응답 형태는 어떤 아이템을 가지고 온다고 가정했을 때, 연관된 모든 테이블을 조인해서 모든 데이터를 가져오고 있다. 필요한 데이터만을 골라 데이터를 보내준다면, 속도가 더 빨라질 것이다. 또한 SQL 문을 수정하는 방법도 있을 것이다. 백엔드 코드의 수정은 이후 개인 프로젝트에서 진행해볼 예정이다.