feat: implement next-gen vectorized engine, async architecture, and modernization roadmap v2.32.0

This commit is contained in:
Wonseok Jung
2026-04-30 23:44:36 +09:00
parent 39d46d7c54
commit cd1d6a3da8
20 changed files with 1086 additions and 282 deletions
+88
View File
@@ -0,0 +1,88 @@
/**
* IDataSource: 데이터 원천에 대한 추상화 인터페이스 (DIP 준수)
*/
export interface IDataSource<T> {
fetch(): Promise<T[]>;
}
/**
* 집계 결과 타입 정의
*/
export interface AggregateResult {
key: string;
count: number;
values: any[];
average?: number;
}
/**
* DataProcessor:
* 시스템의 알고리즘적 효율성과 유지보수성을 극대화하기 위한 핵심 집계 엔진.
* O(N) 복잡도를 보장하며 데이터 분포 민감도를 고려한 최적화 전략을 포함합니다.
*/
export class DataProcessor {
/**
* 핵심 데이터 집계 함수 (Optimized O(N))
* @param data 집계할 데이터 배열
* @param keyPath 집계 기준이 될 속성 경로
*/
public static aggregate(data: any[], keyPath: string): AggregateResult[] {
if (!data || data.length === 0) return [];
// 1. 성능 상충 관계 (Sweet Spot) 고려:
// 데이터가 매우 작을 때는(예: N < 10) 해시 맵 생성 오버헤드가 더 클 수 있으나,
// 일반적인 성능 보장을 위해 해시 기반 단일 패스(Single-Pass) 방식을 기본으로 채택합니다.
const map = new Map<string, AggregateResult>();
for (const item of data) {
try {
const keyValue = this.getNestedValue(item, keyPath);
if (keyValue === undefined || keyValue === null) continue;
const key = String(keyValue);
let entry = map.get(key);
if (!entry) {
entry = {
key,
count: 0,
values: []
};
map.set(key, entry);
}
entry.count++;
entry.values.push(item);
// 수치형 데이터인 경우 평균 계산을 위한 로직 (예시)
if (typeof item.value === 'number') {
// 점진적 평균 계산 등 추가 가능
}
} catch (error) {
// 오류 처리 정밀도 (Error Handling Granularity)
// 특정 아이템 처리 실패가 전체 집계 중단으로 이어지지 않도록 격리
console.warn(`[DataProcessor] Skip item due to error: ${error}`);
}
}
return Array.from(map.values());
}
/**
* 데이터 분포 민감성(Data Distribution Sensitivity)을 고려한 고도화된 집계 (Trie 기반)
* 키가 매우 길거나 계층적인 경우 메모리 및 검색 속도 최적화를 위해 사용합니다.
*/
public static aggregateByTrie(data: any[], keyPath: string): AggregateResult[] {
// TODO: 복잡한 키 구조를 위한 Trie 인덱싱 로직 구현 (Phase 2 확장 예정)
return this.aggregate(data, keyPath);
}
/**
* 중첩된 객체 속성 접근 (Safety handling)
*/
private static getNestedValue(obj: any, path: string): any {
return path.split('.').reduce((prev, curr) => prev && prev[curr], obj);
}
}