라벨명 표시기능
This commit is contained in:
143
backend-node/src/utils/cache.ts
Normal file
143
backend-node/src/utils/cache.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* 간단한 메모리 캐시 구현
|
||||
* 테이블 타입관리 성능 최적화용
|
||||
*/
|
||||
|
||||
interface CacheItem<T> {
|
||||
data: T;
|
||||
timestamp: number;
|
||||
ttl: number; // Time to live in milliseconds
|
||||
}
|
||||
|
||||
class MemoryCache {
|
||||
private cache = new Map<string, CacheItem<any>>();
|
||||
private readonly DEFAULT_TTL = 5 * 60 * 1000; // 5분
|
||||
|
||||
/**
|
||||
* 캐시에 데이터 저장
|
||||
*/
|
||||
set<T>(key: string, data: T, ttl: number = this.DEFAULT_TTL): void {
|
||||
this.cache.set(key, {
|
||||
data,
|
||||
timestamp: Date.now(),
|
||||
ttl,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 캐시에서 데이터 조회
|
||||
*/
|
||||
get<T>(key: string): T | null {
|
||||
const item = this.cache.get(key);
|
||||
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TTL 체크
|
||||
if (Date.now() - item.timestamp > item.ttl) {
|
||||
this.cache.delete(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
return item.data as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 캐시에서 데이터 삭제
|
||||
*/
|
||||
delete(key: string): boolean {
|
||||
return this.cache.delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 패턴으로 캐시 삭제 (테이블 관련 캐시 일괄 삭제용)
|
||||
*/
|
||||
deleteByPattern(pattern: string): number {
|
||||
let deletedCount = 0;
|
||||
const regex = new RegExp(pattern);
|
||||
|
||||
for (const key of this.cache.keys()) {
|
||||
if (regex.test(key)) {
|
||||
this.cache.delete(key);
|
||||
deletedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return deletedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 만료된 캐시 정리
|
||||
*/
|
||||
cleanup(): number {
|
||||
let cleanedCount = 0;
|
||||
const now = Date.now();
|
||||
|
||||
for (const [key, item] of this.cache.entries()) {
|
||||
if (now - item.timestamp > item.ttl) {
|
||||
this.cache.delete(key);
|
||||
cleanedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return cleanedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 캐시 통계
|
||||
*/
|
||||
getStats(): {
|
||||
totalKeys: number;
|
||||
expiredKeys: number;
|
||||
memoryUsage: string;
|
||||
} {
|
||||
const now = Date.now();
|
||||
let expiredKeys = 0;
|
||||
|
||||
for (const item of this.cache.values()) {
|
||||
if (now - item.timestamp > item.ttl) {
|
||||
expiredKeys++;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
totalKeys: this.cache.size,
|
||||
expiredKeys,
|
||||
memoryUsage: `${Math.round(JSON.stringify([...this.cache.entries()]).length / 1024)} KB`,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 전체 캐시 초기화
|
||||
*/
|
||||
clear(): void {
|
||||
this.cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// 싱글톤 인스턴스
|
||||
export const cache = new MemoryCache();
|
||||
|
||||
// 캐시 키 생성 헬퍼
|
||||
export const CacheKeys = {
|
||||
TABLE_LIST: "table_list",
|
||||
TABLE_COLUMNS: (tableName: string, page: number, size: number) =>
|
||||
`table_columns:${tableName}:${page}:${size}`,
|
||||
TABLE_COLUMN_COUNT: (tableName: string) => `table_column_count:${tableName}`,
|
||||
WEB_TYPE_OPTIONS: "web_type_options",
|
||||
COMMON_CODES: (category: string) => `common_codes:${category}`,
|
||||
} as const;
|
||||
|
||||
// 자동 정리 스케줄러 (10분마다)
|
||||
setInterval(
|
||||
() => {
|
||||
const cleaned = cache.cleanup();
|
||||
if (cleaned > 0) {
|
||||
console.log(`[Cache] 만료된 캐시 ${cleaned}개 정리됨`);
|
||||
}
|
||||
},
|
||||
10 * 60 * 1000
|
||||
);
|
||||
|
||||
export default cache;
|
||||
Reference in New Issue
Block a user