110 lines
3.0 KiB
TypeScript
110 lines
3.0 KiB
TypeScript
|
|
/**
|
||
|
|
* 컬럼 매핑 유틸리티
|
||
|
|
* 다중 데이터 소스 통합 시 컬럼명을 통일하기 위한 함수
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 데이터에 컬럼 매핑 적용
|
||
|
|
* @param data 원본 데이터 배열
|
||
|
|
* @param columnMapping 컬럼 매핑 객체 { 원본컬럼: 표시이름 }
|
||
|
|
* @returns 매핑이 적용된 데이터 배열
|
||
|
|
*
|
||
|
|
* @example
|
||
|
|
* const data = [{ name: "상품A", amount: 1000 }];
|
||
|
|
* const mapping = { name: "product", amount: "value" };
|
||
|
|
* const result = applyColumnMapping(data, mapping);
|
||
|
|
* // result: [{ product: "상품A", value: 1000 }]
|
||
|
|
*/
|
||
|
|
export function applyColumnMapping(
|
||
|
|
data: any[],
|
||
|
|
columnMapping?: Record<string, string>
|
||
|
|
): any[] {
|
||
|
|
// 매핑이 없거나 빈 객체면 원본 그대로 반환
|
||
|
|
if (!columnMapping || Object.keys(columnMapping).length === 0) {
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log("🔄 컬럼 매핑 적용 중...", {
|
||
|
|
rowCount: data.length,
|
||
|
|
mappingCount: Object.keys(columnMapping).length,
|
||
|
|
mapping: columnMapping,
|
||
|
|
});
|
||
|
|
|
||
|
|
// 각 행에 매핑 적용
|
||
|
|
const mappedData = data.map((row) => {
|
||
|
|
const mappedRow: any = {};
|
||
|
|
|
||
|
|
// 모든 컬럼 순회
|
||
|
|
Object.keys(row).forEach((originalCol) => {
|
||
|
|
// 매핑이 있으면 매핑된 이름 사용, 없으면 원본 이름 사용
|
||
|
|
const mappedCol = columnMapping[originalCol] || originalCol;
|
||
|
|
mappedRow[mappedCol] = row[originalCol];
|
||
|
|
});
|
||
|
|
|
||
|
|
return mappedRow;
|
||
|
|
});
|
||
|
|
|
||
|
|
console.log("✅ 컬럼 매핑 완료", {
|
||
|
|
originalColumns: Object.keys(data[0] || {}),
|
||
|
|
mappedColumns: Object.keys(mappedData[0] || {}),
|
||
|
|
});
|
||
|
|
|
||
|
|
return mappedData;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 여러 데이터 소스의 데이터를 병합
|
||
|
|
* 각 데이터 소스의 컬럼 매핑을 적용한 후 병합
|
||
|
|
*
|
||
|
|
* @param dataSets 데이터셋 배열 [{ data, columnMapping, source }]
|
||
|
|
* @returns 병합된 데이터 배열
|
||
|
|
*
|
||
|
|
* @example
|
||
|
|
* const dataSets = [
|
||
|
|
* {
|
||
|
|
* data: [{ name: "A", amount: 100 }],
|
||
|
|
* columnMapping: { name: "product", amount: "value" },
|
||
|
|
* source: "DB1"
|
||
|
|
* },
|
||
|
|
* {
|
||
|
|
* data: [{ product_name: "B", total: 200 }],
|
||
|
|
* columnMapping: { product_name: "product", total: "value" },
|
||
|
|
* source: "DB2"
|
||
|
|
* }
|
||
|
|
* ];
|
||
|
|
* const result = mergeDataSources(dataSets);
|
||
|
|
* // result: [
|
||
|
|
* // { product: "A", value: 100, _source: "DB1" },
|
||
|
|
* // { product: "B", value: 200, _source: "DB2" }
|
||
|
|
* // ]
|
||
|
|
*/
|
||
|
|
export function mergeDataSources(
|
||
|
|
dataSets: Array<{
|
||
|
|
data: any[];
|
||
|
|
columnMapping?: Record<string, string>;
|
||
|
|
source?: string;
|
||
|
|
}>
|
||
|
|
): any[] {
|
||
|
|
console.log(`🔗 ${dataSets.length}개의 데이터 소스 병합 중...`);
|
||
|
|
|
||
|
|
const mergedData: any[] = [];
|
||
|
|
|
||
|
|
dataSets.forEach(({ data, columnMapping, source }) => {
|
||
|
|
// 각 데이터셋에 컬럼 매핑 적용
|
||
|
|
const mappedData = applyColumnMapping(data, columnMapping);
|
||
|
|
|
||
|
|
// 소스 정보 추가
|
||
|
|
const dataWithSource = mappedData.map((row) => ({
|
||
|
|
...row,
|
||
|
|
_source: source || "unknown", // 어느 데이터 소스에서 왔는지 표시
|
||
|
|
}));
|
||
|
|
|
||
|
|
mergedData.push(...dataWithSource);
|
||
|
|
});
|
||
|
|
|
||
|
|
console.log(`✅ 데이터 병합 완료: 총 ${mergedData.length}개 행`);
|
||
|
|
|
||
|
|
return mergedData;
|
||
|
|
}
|
||
|
|
|