refactor: extract common bandwidth formatting utilities

- Add BandwidthInfo interface to types.ts (single source of truth)
- Create formatters.ts with formatTB() and formatTrafficInfo()
- Display CDN hit rate and gross/origin traffic in recommendations
- Fix floating point formatting (consistent decimal places)
- Fix undefined handling in toLocaleString() calls
- Unify overage detection logic (overage_tb > 0 && cost > 0)
- Add CDN hit rate range validation (0-100%)
- Extract CDN_CACHE_HIT_RATES constants

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-27 12:33:58 +09:00
parent 0277f0539b
commit 6392a17d4f
4 changed files with 152 additions and 40 deletions

72
src/utils/formatters.ts Normal file
View File

@@ -0,0 +1,72 @@
/**
* formatters.ts - 공통 포맷팅 유틸리티
*
* 목적: 트래픽, 대역폭 정보를 일관되게 포맷팅
*/
import type { BandwidthInfo } from '../types';
/**
* 트래픽 값을 적절한 소수점 자리로 포맷팅
*
* @param value - TB 단위 트래픽 값
* @returns 포맷팅된 문자열 (예: "1.23TB", "12.3TB")
*
* 규칙:
* - 10TB 미만: 소수점 2자리
* - 10TB 이상: 소수점 1자리
*/
export function formatTB(value: number): string {
if (value < 10) {
return `${value.toFixed(2)}TB`;
}
return `${value.toFixed(1)}TB`;
}
/**
* 대역폭 정보를 사용자 친화적 문자열로 포맷팅
*
* @param bandwidth_info - 대역폭 정보 객체
* @param currency - 통화 코드 ('KRW' 또는 'USD')
* @returns 포맷팅된 트래픽 정보 문자열
*
* 포맷:
* - CDN 있음 + 초과: "예상 트래픽: 5.00TB (CDN 85% → 원본 0.75TB) → 초과 0.25TB (₩5,000)"
* - CDN 있음 + 포함: "예상 트래픽: 5.00TB (CDN 85% → 원본 0.75TB)"
* - CDN 없음 + 초과: "예상 트래픽: 1.50TB → 초과 0.50TB (₩10,000)"
* - CDN 없음 + 포함: "예상 트래픽: 0.80TB (포함 범위 내)"
*/
export function formatTrafficInfo(bandwidth_info: BandwidthInfo, currency: string): string {
// CDN 정보가 있는 경우
if (bandwidth_info.gross_monthly_tb !== undefined && bandwidth_info.cdn_cache_hit_rate !== undefined) {
// CDN 캐시 히트율 범위 검증 (0-100%)
const hitRate = Math.round(Math.min(1, Math.max(0, bandwidth_info.cdn_cache_hit_rate)) * 100);
const grossTB = formatTB(bandwidth_info.gross_monthly_tb);
const estimatedTB = formatTB(bandwidth_info.estimated_monthly_tb);
// 초과 여부 판단 (통일된 조건)
if (bandwidth_info.estimated_overage_tb > 0 && bandwidth_info.estimated_overage_cost > 0) {
const overageTB = formatTB(bandwidth_info.estimated_overage_tb);
const overageCost = currency === 'KRW'
? `${Math.round(bandwidth_info.estimated_overage_cost).toLocaleString()}`
: `$${bandwidth_info.estimated_overage_cost.toFixed(2)}`;
return `예상 트래픽: ${grossTB} (CDN ${hitRate}% → 원본 ${estimatedTB}) → 초과 ${overageTB} (${overageCost})`;
} else {
return `예상 트래픽: ${grossTB} (CDN ${hitRate}% → 원본 ${estimatedTB})`;
}
} else {
// CDN 정보 없는 경우
const estimatedTB = formatTB(bandwidth_info.estimated_monthly_tb);
// 초과 여부 판단 (통일된 조건)
if (bandwidth_info.estimated_overage_tb > 0 && bandwidth_info.estimated_overage_cost > 0) {
const overageTB = formatTB(bandwidth_info.estimated_overage_tb);
const overageCost = currency === 'KRW'
? `${Math.round(bandwidth_info.estimated_overage_cost).toLocaleString()}`
: `$${bandwidth_info.estimated_overage_cost.toFixed(2)}`;
return `예상 트래픽: ${estimatedTB} → 초과 ${overageTB} (${overageCost})`;
} else {
return `예상 트래픽: ${estimatedTB} (포함 범위 내)`;
}
}
}