✏️ 개요
사내 최초 in-house 서비스로 예정된 뷰티사업 관리 시스템 MVP 개발을 거듭 진행하다 문득 이왕 사내 in-house 서비스가 될 프로젝트인데 좀 더 신경 써서 최적화하고 싶다는 생각이 들었습니다.
재직 중인 회사는 시니어 개발자가 없고, 신입과 경력 3년 이하 주니어 개발자들로만 구성되어 있어 기본적으로 모든 최적화나 개발 노하우를 직접 찾아내어 공유하고 적용하지 않으면 기술의 부채가 심화되기 때문에 이를 경계하며 꾸준히 더 좋은 방향성을 가져가고자 부단히 노력해 왔던 것 같습니다.
주말 간 최적화 방법에 대해 탐색하다 보니 프론트엔드의 기술로 코드스플리팅, webp활용, preload, image lazy load 등 이미 적용한 최적화 기술들을 많이 소개 해주고 있었습니다. 그래서 이번에는 다른 영역인 DevOps 혹은 Infra 영역에서는 더 최적화 할 수 있지 않을까? 하는 생각이 들어 탐색하다 gzip, brotli, lz4 등 압축 포맷에 대해 알게 되었습니다.
그 중 가장 보편적으로 쓰이고 호환율도 가장 높은 gzip을 적용해보자 했습니다.
gzip은 아주 간단한 설정만으로 작동시킬 수 있었습니다. 빌드 시 번들러 설정으로 빌드 폴더에 .gz 확장자를 가지고 있는 브라우저에서 식별가능하고 압축해제를 직접 할 수 있는 압축파일을 포함시킬 수 있고, 웹서버에서 허용 설정을 추가해주면 정상적으로 빌드된 파일을 브라우저에 띄울 수 있다는 것을 알게 되었습니다.
프론트엔드 역량과는 무관하다고 볼 수 있지만, 저는 UX/DX 지향 개발자이기 때문에 이를 지나칠 수 없었습니다!
번들 사이즈 감소 ➔ 빠른 다운로드 ➔ 빠른 렌더링으로 UX 향상을 기대하며 실무에 적용하게 되었습니다.
🏠 Vite로 gz 파일 생성하기
gzip활용 설정 자체는 전혀 어렵지 않습니다.
vite.config.js 파일에서 default객체의 plugins 배열에서 compression 함수를 추가하고 아래 이미지와 같이 설정해 주면 빌드 시 .gz 확장자를 가진 압출 파일이 동봉됩니다.

설정 후 빌드를 해보면 아래 이미지와 같이 청크파일과 .gz의 확장자를 가진 파일도 함께 생성된 것을 확인할 수 있습니다.

🌐 웹서버에서 .gz 파일 서빙
사내 인프라는 IaaS로 Ubuntu OS를 배포 환경을 ssh를 통하여 운영하고 있습니다.
통합 원격 접속 어플리케이션인 MobaXturm을 사용해서 리눅스 계정에 접속하여 NginX의 default 파일을 설정해 주었습니다.

매우 간단한 설정만을 추가하여 gzip 설정을 할 수 있었습니다.
🔍 index.js로 비교 측정 해보자
실제 사용 환경(Use Case)을 반영한 비교를 위해, 네트워크 속도는 조정하지 않은 상태에서 측정했습니다.

번들사이즈: 1,025 KB
다운로드 속도: 794ms
압축 전에도 성능면에서는 나쁘다기 하기보다 오히려 좋은 수치에 속합니다.

번들사이즈: 330 KB
다운로드 속도: 169ms
압축 후 실제 체감으로는 페이지 접속과 동시에 화면이 보이는 느낌이 들 정도로 매우 빠른 속도로 렌더링이 되었습니다.
그리고 마지막으로 LCP를 비교해 보았습니다.

압축하지 않은 상태도 충분히 좋은 성능을 유지하고 있습니다.

하지만 압축 후에는 더 압도적인 성능을 보여주는 것을 확인할 수 있었습니다.
✨ 정리하자면
- 번들사이즈: [ 1,025 KB ➔ 330 KB ] - 약 3.1배 감소 ( 67.8% )
- 다운로드 속도: [ 794ms ➔ 169ms ] - 약 4.7배 단축 ( 78.7% )
- LCP: [ 1.24s ➔ 0.58s ] - 약 2.1배 단축 ( 53.2% )
🤔 그렇다면 다른 파일은?
"혹시 index.js 파일만 이렇게 압축이 잘 된 것은 아닐까?" 궁금했습니다. 그렇다고 파일을 하나씩 열어보는 것은 너무 미련한 짓인 것 같아 최근 회사 복지로 지원받고 있는 Cursor AI를 활용하여 직접적으로 빌드 압축률을 계산할 수 있는 방법을 물어보았고, 덕분에 유용한 터미널 명령어를 받을 수 있었습니다!
우선 번들 파일들을 리스트로 확인 가능한 명령어를 실행시켜 보았습니다.

확인해 봤을 때 직접 확인했던 index.js의 번들 압축률을 보니 거의 정확히 일치하는 것을 확인할 수 있었습니다. 추가적으로 번들 압축률을 살펴보니 전체적으로 압축이 정상 진행된 것 같아 우려했던 문제는 해결이 되었습니다.
아래 명령어는 번들 파일 압축 리스트를 모두 뽑아주는 명령어입니다.
# 반드시 빌드 명령어를 실행하여 dist가 root 경로에 존재해야 합니다.
# 그리고 경로는 루트 경로가 아니니, 꼭 확인해주세요!
cd C:\Users\{YourProject}\dist\assets
Get-ChildItem -Filter "*.js" | Where-Object {
Test-Path "$($_.FullName).gz"
} | ForEach-Object {
$original = $_.Length
$compressed = (Get-Item "$($_.FullName).gz").Length
$ratio = [math]::Round((1 - $compressed / $original) * 100, 1)
[PSCustomObject]@{
파일명 = $_.Name
원본크기KB = [math]::Round($original / 1KB, 1)
압축크기KB = [math]::Round($compressed / 1KB, 1)
압축률 = "$ratio%"
}
} | Sort-Object -Property 원본크기KB -Descending | Format-Table -AutoSize
추가적으로 통합 압축률을 계산해서 받을 수 있는 명령어를 실행하여 아래와 같은 결과를 얻을 수 있었습니다.

전체적으로 약 69.16% 압축된 것을 보니 압축 효율도 괜찮게 나온 것 같아 뿌듯했습니다.
그리고 아래 명령어는 전체 압축률을 받을 수 있는 명령어입니다.
# 프로젝트 루트에서 실행
cd C:\Users\{YourProject}
# 전체 압축률 계산 스크립트
$originalSize = 0
$compressedSize = 0
Get-ChildItem -Path "dist\assets" -Recurse -File | ForEach-Object {
if ($_.Extension -eq ".gz") {
$compressedSize += $_.Length
} elseif ($_.Extension -match "\.(js|css|html)$") {
# .gz가 있는 파일만 계산
$gzPath = $_.FullName + ".gz"
if (Test-Path $gzPath) {
$originalSize += $_.Length
}
}
}
$compressionRatio = [math]::Round((1 - $compressedSize / $originalSize) * 100, 2)
$originalMB = [math]::Round($originalSize / 1MB, 2)
$compressedMB = [math]::Round($compressedSize / 1MB, 2)
$savedMB = [math]::Round(($originalSize - $compressedSize) / 1MB, 2)
Write-Host "==================================="
Write-Host "📦 빌드 파일 전체 압축 통계"
Write-Host "==================================="
Write-Host "원본 크기: $originalMB MB"
Write-Host "압축 후 크기: $compressedMB MB"
Write-Host "절약된 크기: $savedMB MB"
Write-Host "압축률: $compressionRatio%"
Write-Host "==================================="
🚩결과
가장 큰 성과는 "번들 사이즈 최적화로 이어지는 렌더링 속도 최적화" 입니다.
기대한 모든 성능이 2배 이상 향상되어 UX를 지향하는 저에게는 큰 성과였다고 생각이 듭니다.
간단한 설정 대비 얻는 효과가 큰 것 같아 사내 동료들과 공유하며 자연스럽게 더 좋은 최적화나 다양한 방법론에 대해서 발전된 이야기를 할 수 있게 된 계기가 된 것 같아 더욱 뿌듯했습니다.
앞으로도 동료들과 함께 성장하기 위해 더 노력하며 정진해야겠다는 다짐도 다시금 굳히게 되었습니다.
'Dev Logs' 카테고리의 다른 글
| [ React: PDF Generator ] 맞춤형 PDF 렌더링 성능 최적화 (0) | 2025.11.20 |
|---|---|
| [ Python: Async HTTP ] 사내 LLM 챗봇 서버 비동기 전환을 통한 요청 취소 및 논블로킹 구조 개선기 (1) | 2025.11.15 |
| [ Three.js Camera handling ] Map화면 이탈 현상 막기 (0) | 2025.11.14 |
| [ openapi-generator-cli ] 사내 API 생성 자동화 도입기 (3) | 2025.11.13 |
| [ Error Fix ] Unable to find git in your PATH. (2) | 2025.01.01 |

























