프린세스 다이어리

구글 라이트하우스 활용해서 페이지 성능 개선하기 본문

FE

구글 라이트하우스 활용해서 페이지 성능 개선하기

개발공주 2021. 10. 21. 18:59
728x90

 

구글 라이트하우스는 각자가 관리하는 사이트의 성능과 접근성 등을 테스트하여 SEO에 도움이 될 수 있는 방안을 제안해 주는 툴이다. 라이트하우스 보고서를 활용하는 방법은 이 글에 정리했다. 회사에서 개발한 프로젝트 일부가 첫 로딩 속도가 너무 느려서 라이트하우스를 활용해 성능을 개선해보려고 한다.

 

성능 9점짜리 사이트

역시 측정 결과 극악의 성능을 자랑한다. 인터넷 상에서 본 점수 중에서 가장 낮은 점수다. 배포한 상태는 이거보다는 훨씬 나은데, 로컬 서버로 열어보면 100점 만점에 9점이 나온다. 이제 이것의 성능을 구글 라이트하우스 리포트에 나온 내용을 활용하여 'Performance' 부분을 개선해보려고 한다.

 

1. 압축된 페이로드 응답 받기

 

여기에서 리소스가 압축되지 않은 점이 성능 저하에 가장 큰 원인이다.

 

먼저, 맨 처음으로 제안된 Enable text compression 항목에서는 서버에서 gzip이나 brotli 등로 압축된 응답을 받는 것을 제안하고 있다. 그런데 이유는 모르겠지만 현재 로컬에서도 동일한 api로 요청해서 압축된 리스폰스를 받고 있는데 해당 문제가 발생하고 있다. 상용에 나가 있는 사이트에서 라이트하우스 성능 측정을 하면 해당 문제가 해결된 것으로 나오고 있으므로 다른 원인을 제거하는 데 집중하면 될 것 같다.

 

content-encoding 헤더를 확인하면 서버에서 압축된 응답을 보내주고 있는지 확인 가능하다. 

 

2. 사용하지 않는 CSS 삭제하기

 

Oppertunities 중에서 당장 하기 쉬워 보이는 Reduce unused CSS부터 해 보았다. PurgeCSS 라는 postcss 라이브러리를 통해 사용하지 않는 CSS를 삭제할 수 있다. postcss-purgecss 라는 라이브러리를 설치하고 적용해 보았다.

 

yarn add -D @fullhuman/postcss-purgecss@3.0.0 postcss@7.0.35

 

PostCSS 버전이 8 이상이어야 한다고 해서 맞춰줬는데도 계속 에러가 뜨길래 오랫동안 구글링을 했는데, 결국 purgecss 버전을 낮춤으로써 해결할 수 있었다. 설치 후 루트에 postcss.config.js를 만들어 다음과 같이 작성했다.

 

const purgecss = require('@fullhuman/postcss-purgecss');

module.exports = {
  plugins: [
    purgecss({
      content: ['./src/**/*.vue', './public/index.html'],
      css: ['**/*.css'], 
      whitelistPatterns: [
        /-(leave|enter|appear)(|-(to|from|active))$/,
        /^(?!(|.*?:)cursor-move).+-move$/,
        /^router-link(|-exact)-active$/,
        /data-v-.*/,
      ],
      defaultExtractor(content) {
        const contentWithoutStyleBlocks = content.replace(
          /<style[^]+?<\/style>/gi,
          ''
        );
        return (
          contentWithoutStyleBlocks.match(/[A-Za-z0-9-_/:]*[A-Za-z0-9-_/]+/g) ||
          []
        );
      }, 
    }),
  ],
};

 

그 결과..

 

 

점수가 2점 올랐다. 유의미하게 시간이 줄어든 것은 아니지만 Total Blocking Time이 1,230ms에서 1,050ms로 줄어들었고, 해당 문제는 해결된 것으로 나왔다(10점도 종종 나온다. 이것만으론 점수에 영향이 많이 없는 것 같다).

 

3. 렌더링을 방해하는 CSS 연기하기

 

그 다음으로는 Eliminate render-blocking resources를 해 주기로 했다. 제거할 파일 또한 방금 최적화한 css인데, postcss로 사용하지 않는 css를 제거한다고 해서, 렌더링을 방해하는 요소를 제거한 것은 아닌가 보다. 그래서 web.dev 사이트를 참고하여 <link rel="preload">를 적용했다.

 

    <link
      rel="preload"
      href="https://cdn.jsdelivr.net/npm/vanillajs-datepicker@1.1.4/dist/css/datepicker.min.css"
      as="style"
      onload="this.onload=null;this.rel='stylesheet'"
    />
    <link
      rel="preload"
      href="https://cdn.jsdelivr.net/npm/bulma@0.9.3/css/bulma.min.css"
      as="style"
      onload="this.onload=null;this.rel='stylesheet'"
    />

 

 

개선이 되고 있다. <link rel="preload" as="style">는 CSS를 비동기적으로 요청하고, onload 속성을 사용하면 CSS로드가 완료될 때 CSS를 처리할 수 있다. onload 핸들러를 사용하는 이유는 null을 해 주면 일부 브라우저에서 rel 속성을 전환할 때 핸들러를 다시 호출하는 것을 방지할 수 있기 때문이다. CSS를 이렇게 비동기적으로 요청한다고 해서 페이지가 로딩되는 화면이 달라지는 것은 아니다. 

 

4. 사용하지 않는 자바스크립트 파일 줄이기

 

자바스크립트 리소스를 최적화하지 않으면 한 번에 엄청나게 큰 js 파일이 덩어리로 들어와서 이 한 번의 로딩이 렌더링 시간을 엄청나게 잡아먹는다. 이 부분을 개선하기 위해서 코드 스플리팅을 해 보았다. router 설정 파일에서 특정 라우팅 시점에 필요한 vue 파일만 불러오도록 설정했다. 

 

import { createWebHistory, createRouter } from 'vue-router';
// import Login from '@/pages/Login.vue';
// import Main from '@/pages/Main.vue';
// import Error from '@/pages/Error.vue';

const Login = () => import(/* webpackChunkName: "login" */ '@/pages/Login.vue');
const Main = () => import(/* webpackChunkName: "main" */ '@/pages/Main.vue');
const Error = () => import(/* webpackChunkName: "error" */ '@/pages/Error.vue');

 

 

Total Blocking Time이 900ms에서 530ms로 감소하였다. 

 

 

 

728x90
Comments