소개: 옵션이 아닌 요구사항으로서의 성능
웹 성능은 '시간이 있을 때' 최적화할 수 있는 것이 아닙니다. 밀리초마다 로딩 지연은 사용자 손실로 이어집니다. Google에 따르면 사용자의 53%가 모바일은 로드하는 데 3초 이상 걸리면 사이트를 떠납니다. 그만큼 성과예산 성능을 모호한 목표에서 파이프라인의 측정 가능하고 자동화된 제약으로 전환합니다. CI/CD.
이 기사에서는 완전한 성능 모니터링 시스템을 설정합니다.
예산의 정의로부터 angular.json 통합에
등대 CI GitHub Actions 파이프라인에서
측정항목이 표준을 충족하지 않는 경우 배포합니다.
이 기사에서 배울 내용
- 성과 예산이란 무엇이며 왜 중요한가요?
- 예산을 설정하는 방법
angular.json - Lighthouse CI(lhci) 설치 및 구성 방법
- 파일의 구조
lighthouserc.js - 어설션 및 품질 임계값을 정의하는 방법
- Lighthouse CI를 GitHub Actions와 통합하는 방법
- 시간 경과에 따른 점수를 추적하는 방법
- 번들 크기를 추적하는 방법
- SpeedCurve 및 Calibre와의 비교
- 회귀 발생 시 빌드가 실패하도록 만드는 방법
1. 성과예산이란?
Un 성과예산 하나 이상의 지표에 대해 사전 정의된 최대 한도 성능의. 예산을 초과하면 빌드가 실패하여 배포가 불가능해집니다. 사용자 경험을 저하시키는 코드입니다. 가장 일반적인 예산은 다음과 같습니다.
성과 예산 지표
| 미터법 | 설명 | 권장예산 |
|---|---|---|
| 번들 크기 | JavaScript 및 CSS 파일의 총 크기 | 초기 JS < 300KB(gzip) |
| LCP | 콘텐츠가 포함된 최대 페인트: 가장 큰 항목을 렌더링하는 시간입니다. | < 2.5초 |
| FID/INP | Next Paint와의 상호작용: 인터페이스 응답성 | < 200ms |
| CLS | 누적 레이아웃 변경: 로드 시 시각적 안정성 | < 0.1 |
| FCP | 콘텐츠가 포함된 첫 번째 페인트: 첫 번째로 표시되는 콘텐츠 | 1.8초 미만 |
| TTI | Time to Interactive: 페이지가 상호작용하게 되는 시점 | < 3.8초 |
2.angular.json의 성능 예산
Angular는 현재 번들의 크기를 제어하는 내장 예산 시스템을 제공합니다. 빌드의. 예산이 초과되면 빌드에서 경고 또는 오류가 생성됩니다.
{
"projects": {
"my-app": {
"architect": {
"build": {
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "400kb",
"maximumError": "500kb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "4kb",
"maximumError": "8kb"
},
{
"type": "anyScript",
"maximumWarning": "150kb",
"maximumError": "200kb"
},
{
"type": "any",
"maximumWarning": "300kb",
"maximumError": "500kb"
}
]
}
}
}
}
}
}
}
각도 예산 유형
| 유형 | 설명 |
|---|---|
initial |
초기 번들 크기(기본 + 폴리필 + 스타일) |
anyComponentStyle |
단일 구성 요소 CSS의 크기 |
anyScript |
단일 JavaScript 파일의 크기 |
any |
번들에 포함된 개별 파일의 크기 |
allScript |
모든 JavaScript 파일의 총 크기 |
all |
번들에 포함된 모든 파일의 총 크기 |
bundle |
특정 번들의 크기(이름별) |
3. 등대 CI 설정
LHCI(Lighthouse CI)는 Lighthouse 감사 자동화를 위한 Google의 공식 도구입니다. CI/CD 파이프라인에서. 성능, 접근성, 모범 사례 및 SEO에 대한 점수를 제공합니다.
# Installare Lighthouse CI
npm install -D @lhci/cli
# Oppure globalmente
npm install -g @lhci/cli
# Verificare l'installazione
lhci --version
# Eseguire un audit locale
lhci autorun
Lighthouserc.js 구성
파일 lighthouserc.js 프로젝트 루트에서 다음의 동작을 구성합니다.
등대 CI. 다음은 Angular 프로젝트의 전체 설정입니다.
// lighthouserc.js
module.exports = {
ci: {
collect: {
// Quante volte eseguire l'audit (per risultati stabili)
numberOfRuns: 3,
// URL da testare (dopo aver avviato il server)
url: ['http://localhost:4200/'],
// Avviare il server prima del test
startServerCommand: 'npx ng serve --configuration=production',
startServerReadyPattern: 'Angular Live Development Server',
startServerReadyTimeout: 30000,
// Impostazioni Chrome
settings: {
chromeFlags: '--no-sandbox --headless --disable-gpu',
// Simulare una connessione 4G
throttling: {
rttMs: 150,
throughputKbps: 1638.4,
cpuSlowdownMultiplier: 4,
},
},
},
assert: {
assertions: {
// Performance
'categories:performance': ['error', { minScore: 0.9 }],
'first-contentful-paint': ['warn', { maxNumericValue: 2000 }],
'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
'total-blocking-time': ['warn', { maxNumericValue: 300 }],
'speed-index': ['warn', { maxNumericValue: 3000 }],
// Accessibilita
'categories:accessibility': ['error', { minScore: 0.9 }],
// Best Practice
'categories:best-practices': ['warn', { minScore: 0.9 }],
// SEO
'categories:seo': ['error', { minScore: 0.9 }],
// Audit specifici
'uses-text-compression': 'error',
'uses-responsive-images': 'warn',
'render-blocking-resources': 'warn',
'unused-javascript': 'warn',
},
},
upload: {
// Salvare i risultati come file temporanei
target: 'temporary-public-storage',
},
},
};
어설션의 오류와 경고의 차이점
수준이 있는 어설션 error 빌드가 실패하여 배포가 불가능해집니다.
수준이 있는 어설션 warn 경고를 생성하지만 파이프라인을 차단하지는 않습니다.
미국 error 중요한 지표(LCP, CLS)의 경우 e warn 측정항목의 경우
모니터링합니다(속도 지수, 최적화되지 않은 리소스).
4. GitHub Actions와의 통합
GitHub Actions 파이프라인에서 Lighthouse CI를 실행하기 위한 전체 워크플로는 다음과 같습니다.
# .github/workflows/lighthouse.yml
name: Lighthouse CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
lighthouse:
name: Lighthouse Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build production
run: npx ng build --configuration=production
- name: Run Lighthouse CI
uses: treosh/lighthouse-ci-action@v12
with:
configPath: './lighthouserc.js'
uploadArtifacts: true
temporaryPublicStorage: true
- name: Upload Lighthouse reports
uses: actions/upload-artifact@v4
if: always()
with:
name: lighthouse-reports
path: .lighthouseci/
retention-days: 7
정적 서버를 사용한 대체 구성
보다 안정적인 결과를 얻으려면 정적 서버를 사용하여 프로덕션 빌드를 제공하는 것이 가장 좋습니다.
사용하는 대신 ng serve:
// lighthouserc.js - con server statico
module.exports = {
ci: {
collect: {
numberOfRuns: 5,
url: ['http://localhost:8080/'],
startServerCommand: 'npx http-server dist/my-app/browser -p 8080 -c-1',
startServerReadyPattern: 'Available on',
startServerReadyTimeout: 10000,
settings: {
chromeFlags: '--no-sandbox --headless --disable-gpu',
preset: 'desktop', // oppure 'perf' per mobile simulation
},
},
assert: {
preset: 'lighthouse:recommended',
assertions: {
'categories:performance': ['error', { minScore: 0.9, aggregationMethod: 'median-run' }],
'categories:accessibility': ['error', { minScore: 0.9 }],
'categories:best-practices': ['warn', { minScore: 0.85 }],
'categories:seo': ['error', { minScore: 0.9 }],
},
},
upload: {
target: 'temporary-public-storage',
},
},
};
5. 시간 경과에 따른 점수 추적
성능 변화를 모니터링하려면 기록 점수를 저장하는 것이 유용합니다. 등대 CI는 이 목적을 위해 전용 서버를 지원하거나 더 긴 접근 방식을 사용할 수 있습니다. GitHub Actions 아티팩트로 간단하게:
- name: Extract Lighthouse scores
id: lh-scores
run: |
# Estrarre i punteggi dal report JSON
REPORT=$(find .lighthouseci -name 'lhr-*.json' | head -1)
PERF=$(jq '.categories.performance.score * 100' "$REPORT")
A11Y=$(jq '.categories.accessibility.score * 100' "$REPORT")
BP=$(jq '.categories["best-practices"].score * 100' "$REPORT")
SEO=$(jq '.categories.seo.score * 100' "$REPORT")
echo "performance=$PERF" >> "$GITHUB_OUTPUT"
echo "accessibility=$A11Y" >> "$GITHUB_OUTPUT"
echo "best-practices=$BP" >> "$GITHUB_OUTPUT"
echo "seo=$SEO" >> "$GITHUB_OUTPUT"
- name: Comment PR with scores
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const perf = '${{ steps.lh-scores.outputs.performance }}';
const a11y = '${{ steps.lh-scores.outputs.accessibility }}';
const bp = '${{ steps.lh-scores.outputs.best-practices }}';
const seo = '${{ steps.lh-scores.outputs.seo }}';
const body = `## Lighthouse Scores
| Category | Score |
|----------|-------|
| Performance | ${perf}/100 |
| Accessibility | ${a11y}/100 |
| Best Practices | ${bp}/100 |
| SEO | ${seo}/100 |`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});
6. 번들 크기 추적
Lighthouse 외에도 시간이 지남에 따라 번들의 크기를 모니터링하는 것이 중요합니다. 인상 심각한 문제가 될 때까지 점진적이고 종종 눈에 띄지 않습니다.
# Step per monitorare la dimensione del bundle
- name: Analyze bundle size
run: |
# Calcolare la dimensione totale del bundle
TOTAL=$(find dist/my-app/browser -name '*.js' -o -name '*.css' | \
xargs wc -c | tail -1 | awk '{print $1}')
TOTAL_KB=$((TOTAL / 1024))
echo "Bundle totale: ${TOTAL_KB} KB"
# Calcolare la dimensione gzippata
GZIP_TOTAL=0
for file in $(find dist/my-app/browser -name '*.js' -o -name '*.css'); do
SIZE=$(gzip -c "$file" | wc -c)
GZIP_TOTAL=$((GZIP_TOTAL + SIZE))
done
GZIP_KB=$((GZIP_TOTAL / 1024))
echo "Bundle gzippato: ${GZIP_KB} KB"
# Verificare il budget
MAX_GZIP_KB=400
if [ "$GZIP_KB" -gt "$MAX_GZIP_KB" ]; then
echo "ERRORE: Bundle gzippato (${GZIP_KB} KB) supera il budget (${MAX_GZIP_KB} KB)"
exit 1
fi
시각적 번들 분석기
번들에서 공간을 차지하는 것이 무엇인지 이해하기 위해 Angular는 내장된 시각적 분석기를 제공합니다.
# Generare le statistiche del bundle
npx ng build --configuration=production --stats-json
# Analizzare con webpack-bundle-analyzer
npx webpack-bundle-analyzer dist/my-app/browser/stats.json
# Alternativa: source-map-explorer per analisi più dettagliata
npx source-map-explorer dist/my-app/browser/main.*.js
7. 대체 도구와의 비교
성능 모니터링 도구
| 기구 | 유형 | 비용 | CI 통합 | 다음에 이상적입니다. |
|---|---|---|---|---|
| 등대 CI | 오픈 소스 | 무료 | 토종의 | 모든 프로젝트 |
| 속도곡선 | SaaS | 월 $20부터 | 아피스 | 지속적인 모니터링 |
| 구경 | SaaS | 월 $45부터 | 아피스 | 엔터프라이즈 팀 |
| 번들워치 | 오픈 소스 | 무료 | GitHub 앱 | 번들 크기만 |
| 크기 제한 | 오픈 소스 | 무료 | npm 스크립트 | 빠른 사이즈 확인 |
8. 회귀로 인한 빌드 실패
가장 강력한 구성은 Angular 예산과 Lighthouse CI를 결합하여 성능 회귀에 대한 이중 장벽:
# Pipeline completa con performance gates
name: Performance Pipeline
on:
pull_request:
branches: [main]
jobs:
build-check:
name: Build and Budget Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
# Gate 1: Angular budget check (durante la build)
- name: Build with budget check
run: npx ng build --configuration=production
# La build fallisce se i budget in angular.json sono superati
lighthouse-check:
name: Lighthouse Performance Audit
runs-on: ubuntu-latest
needs: build-check
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npx ng build --configuration=production
# Gate 2: Lighthouse audit (metriche runtime)
- name: Run Lighthouse CI
uses: treosh/lighthouse-ci-action@v12
with:
configPath: './lighthouserc.js'
uploadArtifacts: true
temporaryPublicStorage: true
단계별 구현 전략
- 1주차: 모드에서 Lighthouse CI 실행
warn기준선을 수집하기 위해 - 2주차: 기준선(평균 - 5%)을 기준으로 임계값 설정
- 3주차: 중요한 지표(LCP, CLS)를 다음으로 전달합니다.
error - 4주차: Lighthouse 확인을 요청하려면 분기 보호 규칙을 활성화하세요.
- 진행 중: 팀이 최적화함에 따라 점차적으로 임계값을 강화합니다.
결론
이 기사에서 우리는 완벽한 성능 모니터링 시스템을 구축했습니다. CI/CD 파이프라인에서. 크기 제어를 위해 Angular 예산을 구성했습니다. 번들의 각 풀 요청에서 자동 감사를 위한 통합 Lighthouse CI 및 구현 PR 댓글로 점수를 직접 보고합니다.
핵심 메시지는 성능이 다른 요구사항과 동일하게 취급되어야 한다는 것입니다. 프로젝트: 자동으로 정의, 측정 및 검증됩니다. 예산 및 Lighthouse CI 포함 파이프라인에서 각 회귀는 프로덕션에 도달하기 전에 포착됩니다.
시리즈의 마지막 기사에서 우리는 다음과 같은 문제를 다룰 것입니다. 애플리케이션 모니터링 및 경고 웹: Sentry를 통한 오류 추적, 실제 사용자 모니터링 및 유지 관리 전략 배포 후에도 품질이 유지됩니다.







