배치관리시스템 (DB, RestAPI)
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
import prisma from "../config/database";
|
||||
import { PasswordEncryption } from "../utils/passwordEncryption";
|
||||
import { DatabaseConnectorFactory } from "../database/DatabaseConnectorFactory";
|
||||
import { RestApiConnector } from "../database/RestApiConnector";
|
||||
import { ApiResponse, ColumnInfo, TableInfo } from "../types/batchTypes";
|
||||
|
||||
export class BatchExternalDbService {
|
||||
@@ -686,4 +687,226 @@ export class BatchExternalDbService {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* REST API에서 데이터 조회
|
||||
*/
|
||||
static async getDataFromRestApi(
|
||||
apiUrl: string,
|
||||
apiKey: string,
|
||||
endpoint: string,
|
||||
method: 'GET' | 'POST' | 'PUT' | 'DELETE' = 'GET',
|
||||
columns?: string[],
|
||||
limit: number = 100
|
||||
): Promise<ApiResponse<any[]>> {
|
||||
try {
|
||||
console.log(`[BatchExternalDbService] REST API 데이터 조회: ${apiUrl}${endpoint}`);
|
||||
|
||||
// REST API 커넥터 생성
|
||||
const connector = new RestApiConnector({
|
||||
baseUrl: apiUrl,
|
||||
apiKey: apiKey,
|
||||
timeout: 30000
|
||||
});
|
||||
|
||||
// 연결 테스트
|
||||
await connector.connect();
|
||||
|
||||
// 데이터 조회
|
||||
const result = await connector.executeQuery(endpoint, method);
|
||||
let data = result.rows;
|
||||
|
||||
// 컬럼 필터링 (지정된 컬럼만 추출)
|
||||
if (columns && columns.length > 0) {
|
||||
data = data.map(row => {
|
||||
const filteredRow: any = {};
|
||||
columns.forEach(col => {
|
||||
if (row.hasOwnProperty(col)) {
|
||||
filteredRow[col] = row[col];
|
||||
}
|
||||
});
|
||||
return filteredRow;
|
||||
});
|
||||
}
|
||||
|
||||
// 제한 개수 적용
|
||||
if (limit > 0) {
|
||||
data = data.slice(0, limit);
|
||||
}
|
||||
|
||||
console.log(`[BatchExternalDbService] REST API 데이터 조회 완료: ${data.length}개 레코드`);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: data
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`[BatchExternalDbService] REST API 데이터 조회 오류 (${apiUrl}${endpoint}):`, error);
|
||||
return {
|
||||
success: false,
|
||||
message: "REST API 데이터 조회 중 오류가 발생했습니다.",
|
||||
error: error instanceof Error ? error.message : "알 수 없는 오류"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 템플릿 기반 REST API로 데이터 전송 (DB → REST API 배치용)
|
||||
*/
|
||||
static async sendDataToRestApiWithTemplate(
|
||||
apiUrl: string,
|
||||
apiKey: string,
|
||||
endpoint: string,
|
||||
method: 'POST' | 'PUT' | 'DELETE' = 'POST',
|
||||
templateBody: string,
|
||||
data: any[],
|
||||
urlPathColumn?: string // URL 경로에 사용할 컬럼명 (PUT/DELETE용)
|
||||
): Promise<ApiResponse<{ successCount: number; failedCount: number }>> {
|
||||
try {
|
||||
console.log(`[BatchExternalDbService] 템플릿 기반 REST API 데이터 전송: ${apiUrl}${endpoint}, ${data.length}개 레코드`);
|
||||
console.log(`[BatchExternalDbService] Request Body 템플릿:`, templateBody);
|
||||
|
||||
// REST API 커넥터 생성
|
||||
const connector = new RestApiConnector({
|
||||
baseUrl: apiUrl,
|
||||
apiKey: apiKey,
|
||||
timeout: 30000
|
||||
});
|
||||
|
||||
// 연결 테스트
|
||||
await connector.connect();
|
||||
|
||||
let successCount = 0;
|
||||
let failedCount = 0;
|
||||
|
||||
// 각 레코드를 개별적으로 전송
|
||||
for (const record of data) {
|
||||
try {
|
||||
// 템플릿 처리: {{컬럼명}} → 실제 값으로 치환
|
||||
let processedBody = templateBody;
|
||||
for (const [key, value] of Object.entries(record)) {
|
||||
const placeholder = `{{${key}}}`;
|
||||
let stringValue = '';
|
||||
|
||||
if (value !== null && value !== undefined) {
|
||||
// Date 객체인 경우 다양한 포맷으로 변환
|
||||
if (value instanceof Date) {
|
||||
// ISO 형식: 2025-09-25T07:22:52.000Z
|
||||
stringValue = value.toISOString();
|
||||
|
||||
// 다른 포맷이 필요한 경우 여기서 처리
|
||||
// 예: YYYY-MM-DD 형식
|
||||
// stringValue = value.toISOString().split('T')[0];
|
||||
|
||||
// 예: YYYY-MM-DD HH:mm:ss 형식
|
||||
// stringValue = value.toISOString().replace('T', ' ').replace(/\.\d{3}Z$/, '');
|
||||
} else {
|
||||
stringValue = String(value);
|
||||
}
|
||||
}
|
||||
|
||||
processedBody = processedBody.replace(new RegExp(placeholder.replace(/[{}]/g, '\\$&'), 'g'), stringValue);
|
||||
}
|
||||
|
||||
console.log(`[BatchExternalDbService] 원본 레코드:`, record);
|
||||
console.log(`[BatchExternalDbService] 처리된 Request Body:`, processedBody);
|
||||
|
||||
// JSON 파싱하여 객체로 변환
|
||||
let requestData;
|
||||
try {
|
||||
requestData = JSON.parse(processedBody);
|
||||
} catch (parseError) {
|
||||
console.error(`[BatchExternalDbService] JSON 파싱 오류:`, parseError);
|
||||
throw new Error(`Request Body JSON 파싱 실패: ${parseError}`);
|
||||
}
|
||||
|
||||
// URL 경로 파라미터 처리 (PUT/DELETE용)
|
||||
let finalEndpoint = endpoint;
|
||||
if ((method === 'PUT' || method === 'DELETE') && urlPathColumn && record[urlPathColumn]) {
|
||||
// /api/users → /api/users/user123
|
||||
finalEndpoint = `${endpoint}/${record[urlPathColumn]}`;
|
||||
}
|
||||
|
||||
console.log(`[BatchExternalDbService] 실행할 API 호출: ${method} ${finalEndpoint}`);
|
||||
console.log(`[BatchExternalDbService] 전송할 데이터:`, requestData);
|
||||
|
||||
await connector.executeQuery(finalEndpoint, method, requestData);
|
||||
successCount++;
|
||||
} catch (error) {
|
||||
console.error(`REST API 레코드 전송 실패:`, error);
|
||||
failedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[BatchExternalDbService] 템플릿 기반 REST API 데이터 전송 완료: 성공 ${successCount}개, 실패 ${failedCount}개`);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: { successCount, failedCount }
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`[BatchExternalDbService] 템플릿 기반 REST API 데이터 전송 오류:`, error);
|
||||
return {
|
||||
success: false,
|
||||
message: `REST API 데이터 전송 실패: ${error}`,
|
||||
data: { successCount: 0, failedCount: 0 }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* REST API로 데이터 전송 (기존 메서드)
|
||||
*/
|
||||
static async sendDataToRestApi(
|
||||
apiUrl: string,
|
||||
apiKey: string,
|
||||
endpoint: string,
|
||||
method: 'POST' | 'PUT' = 'POST',
|
||||
data: any[]
|
||||
): Promise<ApiResponse<{ successCount: number; failedCount: number }>> {
|
||||
try {
|
||||
console.log(`[BatchExternalDbService] REST API 데이터 전송: ${apiUrl}${endpoint}, ${data.length}개 레코드`);
|
||||
|
||||
// REST API 커넥터 생성
|
||||
const connector = new RestApiConnector({
|
||||
baseUrl: apiUrl,
|
||||
apiKey: apiKey,
|
||||
timeout: 30000
|
||||
});
|
||||
|
||||
// 연결 테스트
|
||||
await connector.connect();
|
||||
|
||||
let successCount = 0;
|
||||
let failedCount = 0;
|
||||
|
||||
// 각 레코드를 개별적으로 전송
|
||||
for (const record of data) {
|
||||
try {
|
||||
console.log(`[BatchExternalDbService] 실행할 API 호출: ${method} ${endpoint}`);
|
||||
console.log(`[BatchExternalDbService] 전송할 데이터:`, record);
|
||||
|
||||
await connector.executeQuery(endpoint, method, record);
|
||||
successCount++;
|
||||
} catch (error) {
|
||||
console.error(`REST API 레코드 전송 실패:`, error);
|
||||
failedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`[BatchExternalDbService] REST API 데이터 전송 완료: 성공 ${successCount}개, 실패 ${failedCount}개`);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: { successCount, failedCount }
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`[BatchExternalDbService] REST API 데이터 전송 오류 (${apiUrl}${endpoint}):`, error);
|
||||
return {
|
||||
success: false,
|
||||
message: "REST API 데이터 전송 중 오류가 발생했습니다.",
|
||||
error: error instanceof Error ? error.message : "알 수 없는 오류"
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user