@restnfeel/agentc-starter-kit
Version:
한국어 기업용 CMS 모듈 - Task Master AI와 함께 빠르게 웹사이트를 구현할 수 있는 재사용 가능한 컴포넌트 시스템
224 lines (201 loc) • 5.36 kB
text/typescript
export interface CDNConfig {
provider: "cloudflare" | "aws-cloudfront" | "google-cloud-cdn" | "azure-cdn";
endpoint: string;
customDomain?: string;
accessKey?: string;
secretKey?: string;
distributionId?: string;
zone?: string;
enabled: boolean;
cacheSettings: {
[mimeType: string]: {
maxAge: number; // 초 단위
staleWhileRevalidate: number;
staleIfError: number;
};
};
}
export interface CDNProvider {
upload(file: Buffer, key: string, mimeType: string): Promise<string>;
delete(key: string): Promise<void>;
invalidate(keys: string[]): Promise<void>;
getUrl(key: string): string;
getCacheHeaders(mimeType: string): Record<string, string>;
}
// 기본 캐시 설정
export const DEFAULT_CACHE_SETTINGS = {
// 이미지
"image/jpeg": {
maxAge: 31536000,
staleWhileRevalidate: 86400,
staleIfError: 604800,
},
"image/png": {
maxAge: 31536000,
staleWhileRevalidate: 86400,
staleIfError: 604800,
},
"image/gif": {
maxAge: 31536000,
staleWhileRevalidate: 86400,
staleIfError: 604800,
},
"image/webp": {
maxAge: 31536000,
staleWhileRevalidate: 86400,
staleIfError: 604800,
},
"image/avif": {
maxAge: 31536000,
staleWhileRevalidate: 86400,
staleIfError: 604800,
},
// 비디오
"video/mp4": {
maxAge: 31536000,
staleWhileRevalidate: 86400,
staleIfError: 604800,
},
"video/webm": {
maxAge: 31536000,
staleWhileRevalidate: 86400,
staleIfError: 604800,
},
// 오디오
"audio/mp3": {
maxAge: 31536000,
staleWhileRevalidate: 86400,
staleIfError: 604800,
},
"audio/wav": {
maxAge: 31536000,
staleWhileRevalidate: 86400,
staleIfError: 604800,
},
"audio/ogg": {
maxAge: 31536000,
staleWhileRevalidate: 86400,
staleIfError: 604800,
},
// 문서
"application/pdf": {
maxAge: 86400,
staleWhileRevalidate: 3600,
staleIfError: 86400,
},
"application/msword": {
maxAge: 86400,
staleWhileRevalidate: 3600,
staleIfError: 86400,
},
"text/plain": {
maxAge: 86400,
staleWhileRevalidate: 3600,
staleIfError: 86400,
},
// 기본값
default: { maxAge: 3600, staleWhileRevalidate: 300, staleIfError: 3600 },
};
// 환경변수에서 CDN 설정 로드
export function loadCDNConfig(): CDNConfig {
return {
provider:
(process.env.CDN_PROVIDER as CDNConfig["provider"]) || "cloudflare",
endpoint: process.env.CDN_ENDPOINT || "",
customDomain: process.env.CDN_CUSTOM_DOMAIN,
accessKey: process.env.CDN_ACCESS_KEY,
secretKey: process.env.CDN_SECRET_KEY,
distributionId: process.env.CDN_DISTRIBUTION_ID,
zone: process.env.CDN_ZONE,
enabled: process.env.CDN_ENABLED === "true",
cacheSettings: {
...DEFAULT_CACHE_SETTINGS,
// 환경별 오버라이드 가능
},
};
}
// 파일 키 생성 (CDN에서 사용할 경로)
export function generateCDNKey(fileName: string, uploadId?: string): string {
const timestamp = Date.now();
const randomString = Math.random().toString(36).substring(2, 8);
if (uploadId) {
return `media/${uploadId}/${fileName}`;
}
return `media/${timestamp}-${randomString}/${fileName}`;
}
// MIME 타입으로 적절한 캐시 설정 가져오기
export function getCacheSettingsForMimeType(mimeType: string) {
return (
DEFAULT_CACHE_SETTINGS[mimeType as keyof typeof DEFAULT_CACHE_SETTINGS] ||
DEFAULT_CACHE_SETTINGS.default
);
}
// CDN URL 검증
export function isValidCDNUrl(url: string, config: CDNConfig): boolean {
if (!config.enabled) return false;
const validDomains = [config.endpoint];
if (config.customDomain) {
validDomains.push(config.customDomain);
}
try {
const urlObj = new URL(url);
return validDomains.some(
(domain) =>
urlObj.hostname === domain || urlObj.hostname.endsWith(`.${domain}`)
);
} catch {
return false;
}
}
// CDN 상태 확인
export async function checkCDNHealth(config: CDNConfig): Promise<{
healthy: boolean;
latency?: number;
error?: string;
}> {
if (!config.enabled) {
return { healthy: false, error: "CDN disabled" };
}
const startTime = Date.now();
try {
const testUrl = config.customDomain
? `https://${config.customDomain}/health-check`
: `${config.endpoint}/health-check`;
const response = await fetch(testUrl, {
method: "HEAD",
signal: AbortSignal.timeout(5000),
});
const latency = Date.now() - startTime;
return {
healthy: response.ok,
latency,
error: response.ok ? undefined : `HTTP ${response.status}`,
};
} catch (error) {
return {
healthy: false,
latency: Date.now() - startTime,
error: error instanceof Error ? error.message : "Unknown error",
};
}
}
// CDN 통계
export interface CDNStats {
totalRequests: number;
cacheHitRate: number;
bandwidthUsed: number; // bytes
averageLatency: number; // ms
errorRate: number;
lastUpdated: Date;
}
// 모의 CDN 통계 (실제 구현에서는 각 프로바이더 API 사용)
export function getMockCDNStats(): CDNStats {
return {
totalRequests: 150000,
cacheHitRate: 0.94,
bandwidthUsed: 2.5 * 1024 * 1024 * 1024, // 2.5GB
averageLatency: 45,
errorRate: 0.002,
lastUpdated: new Date(),
};
}