본문 바로가기

카테고리 없음

Lighthouse의 처참한 성능 점수를 보고 최적화 시작...

원래 점수는 96점이였지만 고객의 요구를 듣고 수정하다보니 44점까지 떨어졌다....

 

하..ㅋㅋㅋㅋ원인을 하나하나 살펴보고 해결해보자.

보고서에서 텍스트 기반 리소스(HTML, CSS, JS 등)의 압축이 부족하다고 하니 그래..압축해줄게..

 

우선 나는 백엔드 없이 프론트엔드 혼자서 외주를 하고있는거기 때문에
Firebase Hosting에서 텍스트 압축 활성화를 시켜줬다.

 

Firebase에 텍스트 압축 활성화 및 캐싱 및 헤더 적용

Firebase Hosting은 기본적으로 gzip과 brotli를 지원하지만, 직접 활성화하거나 특정 파일을 더 잘 관리하려면 firebase.json 설정 파일을 직접 수정해야 한다!

캐싱과 헤더 설정은 리소스 요청 수를 줄이고, 사용자 경험을 개선하는 데 중요하다..

 

{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "functions": [
    {
      "source": "functions",
      "codebase": "default",
      "ignore": [
        "node_modules",
        ".git",
        "firebase-debug.log",
        "firebase-debug.*.log",
        "*.local"
      ]
    }
  ],
  "hosting": {
    "public": "dist",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ],
    "headers": [
      {
        "source": "**/*.@(html|js|css|json|xml|svg|webp|png|jpg|jpeg|ico)",
        "headers": [
          {
            "key": "Content-Encoding",
            "value": "gzip" // Gzip 압축 활성화
          },
          {
            "key": "Content-Encoding",
            "value": "br" // Brotli 압축 활성화
          },
          {
            "key": "Cache-Control",
            "value": "public, max-age=31536000, immutable" // 장기 캐싱 설정
          }
        ]
      },
      {
        "source": "/sitemap.xml",
        "headers": [
          {
            "key": "Content-Type",
            "value": "application/xml"
          }
        ]
      }
    ]
  },
  "storage": {
    "rules": "storage.rules"
  }
}

Vite에서 압축 플러그인 추가

Firebase Hosting이 브라우저에서 압축된 파일을 서비스하려면,

빌드 시 브라우저가 인식할 수 있도록 파일을 brotli 또는 gzip으로 압축해야 한다잉..

 

우선 압축 플러그인 비쥬얼코드에 설치!

npm install vite-plugin-compression

 

vite.config.js 설정

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import compression from "vite-plugin-compression";

export default defineConfig({
  plugins: [
    react(),
    // Brotli 압축 플러그인 추가
    compression({
      algorithm: "brotliCompress", // Brotli를 사용하여 파일 압축
      ext: ".br", // 확장자 추가
      threshold: 10240, // 10KB 이상의 파일만 압축
      deleteOriginFile: false, // 원본 파일 유지
    }),
    // Gzip 압축 플러그인 추가
    compression({
      algorithm: "gzip", // Gzip 압축
      ext: ".gz", // 확장자 추가
      threshold: 10240, // 10KB 이상의 파일만 압축
      deleteOriginFile: false, // 원본 파일 유지
    }),
  ],

  build: {
    outDir: "dist", // Firebase Hosting 디렉토리와 일치시킴
    sourcemap: true, // 디버깅 용도로 소스맵 활성화
    chunkSizeWarningLimit: 1500, // 청크 크기 경고 제한 늘리기
    rollupOptions: {
      output: {
        manualChunks: (id) => {
          if (id.includes("node_modules")) {
            return "vendor"; // 외부 라이브러리를 별도 청크로 분리
          }
        },
      },
    },
  },

  server: {
    historyApiFallback: true, // SPA 라우팅 지원
    hmr: {
      overlay: false, // HMR 에러 오버레이 비활성화
    },
  },
});

 

  • Brotli 및 Gzip 압축 활성화:
    • vite-plugin-compression 플러그인을 사용해 Brotli(.br)와 Gzip(.gz) 압축을 모두 활성화함
    • 압축된 파일은 Firebase Hosting에서 최적화된 방식으로 전달됨
  • Chunk 분리:
    • node_modules에 포함된 라이브러리를 vendor라는 별도 청크로 분리해 번들 크기를 줄임
  • Sourcemap 활성화:
    • sourcemap: true를 추가하여 디버깅 중에 번들된 코드와 원본 소스 간 매핑을 제공함
  • 빌드 디렉토리 설정:
    • outDir: "dist"로 Firebase Hosting과 일치하도록 설정함
  • 서버 설정:
    • historyApiFallback: true로 SPA 라우팅을 지원하며, HMR 오버레이를 비활성화함

 

 

자 이제 또 어디가 가장 큰 문제인지 체크해보니 CSS 렌더링 최적화를 하란다.

코드를 살펴보면서 문제를 찾아보니 맙소사...

@media 처리를 해서 각 크기별로 글자 크기와 마진값을 설정해놨는데 정작 기본값은 셋팅을 안해놨다...

재빠르게 수정 ㄱㄱ

HeroText, ServiceHeroText와 같은 텍스트 요소는 브라우저가 로딩되기 전에 스타일을 렌더링해야 하므로, Critical CSS를 추출하거나 기본적으로 간단한 스타일을 적용해야하는걸 잊지말자...!

 

 

더 고칠문제가 남았지만 이제까지 한 고생이 있어 참지 못하고 npm run build 후 firebase deploy를 해서

Lighthouse를 다시 돌려보았따!

오잉...?

 

점수가 다시 높아졌다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ그럼 다른 문제는 시간관계상 나중에 시간이 넘치면 해야겠다ㅎ

이만 끄읕!