2025-10-01 11:55:50 +09:00
|
|
|
# 📋 Phase 3.15: Batch Services Raw Query 전환 계획
|
|
|
|
|
|
|
|
|
|
## 📋 개요
|
|
|
|
|
|
|
|
|
|
배치 관련 서비스들은 총 **24개의 Prisma 호출**이 있으며, 배치 작업 실행 및 관리를 담당합니다.
|
|
|
|
|
|
|
|
|
|
### 📊 기본 정보
|
|
|
|
|
|
2025-10-01 13:30:20 +09:00
|
|
|
| 항목 | 내용 |
|
|
|
|
|
| --------------- | ---------------------------------------------------------- |
|
|
|
|
|
| 대상 서비스 | 4개 (BatchExternalDb, ExecutionLog, Management, Scheduler) |
|
|
|
|
|
| 파일 위치 | `backend-node/src/services/batch*.ts` |
|
|
|
|
|
| 총 파일 크기 | 2,161 라인 |
|
2025-10-01 14:33:08 +09:00
|
|
|
| Prisma 호출 | 0개 (전환 완료) |
|
2025-10-01 13:30:20 +09:00
|
|
|
| **현재 진행률** | **24/24 (100%)** ✅ **전환 완료** |
|
|
|
|
|
| 복잡도 | 높음 (외부 DB 연동, 스케줄링, 트랜잭션) |
|
|
|
|
|
| 우선순위 | 🔴 높음 (Phase 3.15) |
|
|
|
|
|
| **상태** | ✅ **완료** |
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## ✅ 전환 완료 내역
|
|
|
|
|
|
|
|
|
|
### 전환된 Prisma 호출 (24개)
|
|
|
|
|
|
|
|
|
|
#### 1. BatchExternalDbService (8개)
|
2025-10-01 14:33:08 +09:00
|
|
|
|
2025-10-01 13:30:20 +09:00
|
|
|
- `getAvailableConnections()` - findMany → query
|
|
|
|
|
- `getTables()` - $queryRaw → query (information_schema)
|
|
|
|
|
- `getTableColumns()` - $queryRaw → query (information_schema)
|
|
|
|
|
- `getExternalTables()` - findUnique → queryOne (x5)
|
|
|
|
|
|
|
|
|
|
#### 2. BatchExecutionLogService (7개)
|
2025-10-01 14:33:08 +09:00
|
|
|
|
2025-10-01 13:30:20 +09:00
|
|
|
- `getExecutionLogs()` - findMany + count → query (JOIN + 동적 WHERE)
|
|
|
|
|
- `createExecutionLog()` - create → queryOne (INSERT RETURNING)
|
|
|
|
|
- `updateExecutionLog()` - update → queryOne (동적 UPDATE)
|
|
|
|
|
- `deleteExecutionLog()` - delete → query
|
|
|
|
|
- `getLatestExecutionLog()` - findFirst → queryOne
|
|
|
|
|
- `getExecutionStats()` - findMany → query (동적 WHERE)
|
|
|
|
|
|
|
|
|
|
#### 3. BatchManagementService (5개)
|
2025-10-01 14:33:08 +09:00
|
|
|
|
2025-10-01 13:30:20 +09:00
|
|
|
- `getAvailableConnections()` - findMany → query
|
|
|
|
|
- `getTables()` - $queryRaw → query (information_schema)
|
|
|
|
|
- `getTableColumns()` - $queryRaw → query (information_schema)
|
|
|
|
|
- `getExternalTables()` - findUnique → queryOne (x2)
|
|
|
|
|
|
|
|
|
|
#### 4. BatchSchedulerService (4개)
|
2025-10-01 14:33:08 +09:00
|
|
|
|
2025-10-01 13:30:20 +09:00
|
|
|
- `loadActiveBatchConfigs()` - findMany → query (JOIN with json_agg)
|
|
|
|
|
- `updateBatchSchedule()` - findUnique → query (JOIN with json_agg)
|
|
|
|
|
- `getDataFromSource()` - $queryRawUnsafe → query
|
|
|
|
|
- `insertDataToTarget()` - $executeRawUnsafe → query
|
|
|
|
|
|
|
|
|
|
### 주요 기술적 해결 사항
|
|
|
|
|
|
|
|
|
|
1. **외부 DB 연결 조회 반복**
|
2025-10-01 14:33:08 +09:00
|
|
|
|
2025-10-01 13:30:20 +09:00
|
|
|
- 5개의 `findUnique` 호출을 `queryOne`으로 일괄 전환
|
|
|
|
|
- 암호화/복호화 로직 유지
|
|
|
|
|
|
|
|
|
|
2. **배치 설정 + 매핑 JOIN**
|
2025-10-01 14:33:08 +09:00
|
|
|
|
2025-10-01 13:30:20 +09:00
|
|
|
- Prisma `include` → `json_agg` + `json_build_object`
|
|
|
|
|
- `FILTER (WHERE bm.id IS NOT NULL)` 로 NULL 방지
|
|
|
|
|
- 계층적 JSON 데이터 생성
|
|
|
|
|
|
|
|
|
|
3. **동적 WHERE 절 생성**
|
2025-10-01 14:33:08 +09:00
|
|
|
|
2025-10-01 13:30:20 +09:00
|
|
|
- 조건부 필터링 (batch_config_id, execution_status, 날짜 범위)
|
|
|
|
|
- 파라미터 인덱스 동적 관리
|
|
|
|
|
|
|
|
|
|
4. **동적 UPDATE 쿼리**
|
2025-10-01 14:33:08 +09:00
|
|
|
|
2025-10-01 13:30:20 +09:00
|
|
|
- undefined 필드 제외
|
|
|
|
|
- 8개 필드의 조건부 업데이트
|
|
|
|
|
|
|
|
|
|
5. **통계 쿼리 전환**
|
|
|
|
|
- 클라이언트 사이드 집계 유지
|
|
|
|
|
- 원본 데이터만 쿼리로 조회
|
|
|
|
|
|
|
|
|
|
### 컴파일 상태
|
2025-10-01 14:33:08 +09:00
|
|
|
|
2025-10-01 13:30:20 +09:00
|
|
|
✅ TypeScript 컴파일 성공
|
|
|
|
|
✅ Linter 오류 없음
|
2025-10-01 11:55:50 +09:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 🔍 서비스별 상세 분석
|
|
|
|
|
|
|
|
|
|
### 1. BatchExternalDbService (8개 호출, 943 라인)
|
|
|
|
|
|
|
|
|
|
**주요 기능**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- 외부 DB에서 배치 데이터 조회
|
|
|
|
|
- 외부 DB로 배치 데이터 저장
|
|
|
|
|
- 외부 DB 연결 관리
|
|
|
|
|
- 데이터 변환 및 매핑
|
|
|
|
|
|
|
|
|
|
**예상 Prisma 호출**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- `getExternalDbConnection()` - 외부 DB 연결 정보 조회
|
|
|
|
|
- `fetchDataFromExternalDb()` - 외부 DB 데이터 조회
|
|
|
|
|
- `saveDataToExternalDb()` - 외부 DB 데이터 저장
|
|
|
|
|
- `validateExternalDbConnection()` - 연결 검증
|
|
|
|
|
- `getExternalDbTables()` - 테이블 목록 조회
|
|
|
|
|
- `getExternalDbColumns()` - 컬럼 정보 조회
|
|
|
|
|
- `executeBatchQuery()` - 배치 쿼리 실행
|
|
|
|
|
- `getBatchExecutionStatus()` - 실행 상태 조회
|
|
|
|
|
|
|
|
|
|
**기술적 고려사항**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- 다양한 DB 타입 지원 (PostgreSQL, MySQL, Oracle, MSSQL)
|
|
|
|
|
- 연결 풀 관리
|
|
|
|
|
- 트랜잭션 처리
|
|
|
|
|
- 에러 핸들링 및 재시도
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
### 2. BatchExecutionLogService (7개 호출, 299 라인)
|
|
|
|
|
|
|
|
|
|
**주요 기능**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- 배치 실행 로그 생성
|
|
|
|
|
- 배치 실행 이력 조회
|
|
|
|
|
- 배치 실행 통계
|
|
|
|
|
- 로그 정리
|
|
|
|
|
|
|
|
|
|
**예상 Prisma 호출**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- `createExecutionLog()` - 실행 로그 생성
|
|
|
|
|
- `updateExecutionLog()` - 실행 로그 업데이트
|
|
|
|
|
- `getExecutionLogs()` - 실행 로그 목록 조회
|
|
|
|
|
- `getExecutionLogById()` - 실행 로그 단건 조회
|
|
|
|
|
- `getExecutionStats()` - 실행 통계 조회
|
|
|
|
|
- `cleanupOldLogs()` - 오래된 로그 삭제
|
|
|
|
|
- `getFailedExecutions()` - 실패한 실행 조회
|
|
|
|
|
|
|
|
|
|
**기술적 고려사항**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- 대용량 로그 처리
|
|
|
|
|
- 통계 쿼리 최적화
|
|
|
|
|
- 로그 보관 정책
|
|
|
|
|
- 페이징 및 필터링
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
### 3. BatchManagementService (5개 호출, 373 라인)
|
|
|
|
|
|
|
|
|
|
**주요 기능**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- 배치 작업 설정 관리
|
|
|
|
|
- 배치 작업 실행
|
|
|
|
|
- 배치 작업 중지
|
|
|
|
|
- 배치 작업 모니터링
|
|
|
|
|
|
|
|
|
|
**예상 Prisma 호출**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- `getBatchJobs()` - 배치 작업 목록 조회
|
|
|
|
|
- `getBatchJob()` - 배치 작업 단건 조회
|
|
|
|
|
- `createBatchJob()` - 배치 작업 생성
|
|
|
|
|
- `updateBatchJob()` - 배치 작업 수정
|
|
|
|
|
- `deleteBatchJob()` - 배치 작업 삭제
|
|
|
|
|
|
|
|
|
|
**기술적 고려사항**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- JSON 설정 필드 (job_config)
|
|
|
|
|
- 작업 상태 관리
|
|
|
|
|
- 동시 실행 제어
|
|
|
|
|
- 의존성 관리
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
### 4. BatchSchedulerService (4개 호출, 546 라인)
|
|
|
|
|
|
|
|
|
|
**주요 기능**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- 배치 스케줄 설정
|
|
|
|
|
- Cron 표현식 관리
|
|
|
|
|
- 스케줄 실행
|
|
|
|
|
- 다음 실행 시간 계산
|
|
|
|
|
|
|
|
|
|
**예상 Prisma 호출**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- `getScheduledBatches()` - 스케줄된 배치 조회
|
|
|
|
|
- `createSchedule()` - 스케줄 생성
|
|
|
|
|
- `updateSchedule()` - 스케줄 수정
|
|
|
|
|
- `deleteSchedule()` - 스케줄 삭제
|
|
|
|
|
|
|
|
|
|
**기술적 고려사항**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- Cron 표현식 파싱
|
|
|
|
|
- 시간대 처리
|
|
|
|
|
- 실행 이력 추적
|
|
|
|
|
- 스케줄 충돌 방지
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 💡 통합 전환 전략
|
|
|
|
|
|
|
|
|
|
### Phase 1: 핵심 서비스 전환 (12개)
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
**BatchManagementService (5개) + BatchExecutionLogService (7개)**
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- 배치 관리 및 로깅 기능 우선
|
|
|
|
|
- 상대적으로 단순한 CRUD
|
|
|
|
|
|
|
|
|
|
### Phase 2: 스케줄러 전환 (4개)
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
**BatchSchedulerService (4개)**
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- 스케줄 관리
|
|
|
|
|
- Cron 표현식 처리
|
|
|
|
|
|
|
|
|
|
### Phase 3: 외부 DB 연동 전환 (8개)
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
**BatchExternalDbService (8개)**
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- 가장 복잡한 서비스
|
|
|
|
|
- 외부 DB 연결 및 쿼리
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 💻 전환 예시
|
|
|
|
|
|
|
|
|
|
### 예시 1: 배치 실행 로그 생성
|
|
|
|
|
|
|
|
|
|
**변경 전**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
```typescript
|
|
|
|
|
const log = await prisma.batch_execution_logs.create({
|
|
|
|
|
data: {
|
|
|
|
|
batch_id: batchId,
|
|
|
|
|
status: "running",
|
|
|
|
|
started_at: new Date(),
|
|
|
|
|
execution_params: params,
|
|
|
|
|
company_code: companyCode,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**변경 후**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
```typescript
|
|
|
|
|
const log = await queryOne<any>(
|
|
|
|
|
`INSERT INTO batch_execution_logs
|
|
|
|
|
(batch_id, status, started_at, execution_params, company_code)
|
|
|
|
|
VALUES ($1, $2, NOW(), $3, $4)
|
|
|
|
|
RETURNING *`,
|
|
|
|
|
[batchId, "running", JSON.stringify(params), companyCode]
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 예시 2: 배치 통계 조회
|
|
|
|
|
|
|
|
|
|
**변경 전**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
```typescript
|
|
|
|
|
const stats = await prisma.batch_execution_logs.groupBy({
|
|
|
|
|
by: ["status"],
|
|
|
|
|
where: {
|
|
|
|
|
batch_id: batchId,
|
|
|
|
|
started_at: { gte: startDate, lte: endDate },
|
|
|
|
|
},
|
|
|
|
|
_count: { id: true },
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**변경 후**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
```typescript
|
|
|
|
|
const stats = await query<{ status: string; count: string }>(
|
|
|
|
|
`SELECT status, COUNT(*) as count
|
|
|
|
|
FROM batch_execution_logs
|
|
|
|
|
WHERE batch_id = $1
|
|
|
|
|
AND started_at >= $2
|
|
|
|
|
AND started_at <= $3
|
|
|
|
|
GROUP BY status`,
|
|
|
|
|
[batchId, startDate, endDate]
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 예시 3: 외부 DB 연결 및 쿼리
|
|
|
|
|
|
|
|
|
|
**변경 전**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
```typescript
|
|
|
|
|
// 연결 정보 조회
|
|
|
|
|
const connection = await prisma.external_db_connections.findUnique({
|
|
|
|
|
where: { id: connectionId },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 외부 DB 쿼리 실행 (Prisma 사용 불가, 이미 Raw Query일 가능성)
|
|
|
|
|
const externalData = await externalDbClient.query(sql);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**변경 후**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
```typescript
|
|
|
|
|
// 연결 정보 조회
|
|
|
|
|
const connection = await queryOne<any>(
|
|
|
|
|
`SELECT * FROM external_db_connections WHERE id = $1`,
|
|
|
|
|
[connectionId]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 외부 DB 쿼리 실행 (기존 로직 유지)
|
|
|
|
|
const externalData = await externalDbClient.query(sql);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 예시 4: 스케줄 관리
|
|
|
|
|
|
|
|
|
|
**변경 전**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
```typescript
|
|
|
|
|
const schedule = await prisma.batch_schedules.create({
|
|
|
|
|
data: {
|
|
|
|
|
batch_id: batchId,
|
|
|
|
|
cron_expression: cronExp,
|
|
|
|
|
is_active: true,
|
|
|
|
|
next_run_at: calculateNextRun(cronExp),
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**변경 후**:
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
```typescript
|
|
|
|
|
const nextRun = calculateNextRun(cronExp);
|
|
|
|
|
|
|
|
|
|
const schedule = await queryOne<any>(
|
|
|
|
|
`INSERT INTO batch_schedules
|
|
|
|
|
(batch_id, cron_expression, is_active, next_run_at, created_at, updated_at)
|
|
|
|
|
VALUES ($1, $2, $3, $4, NOW(), NOW())
|
|
|
|
|
RETURNING *`,
|
|
|
|
|
[batchId, cronExp, true, nextRun]
|
|
|
|
|
);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 🔧 기술적 고려사항
|
|
|
|
|
|
|
|
|
|
### 1. 외부 DB 연결 관리
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
```typescript
|
|
|
|
|
import { DatabaseConnectorFactory } from "../database/connectorFactory";
|
|
|
|
|
|
|
|
|
|
// 외부 DB 연결 생성
|
|
|
|
|
const connector = DatabaseConnectorFactory.create(connection);
|
|
|
|
|
const externalClient = await connector.connect();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 쿼리 실행
|
|
|
|
|
const result = await externalClient.query(sql, params);
|
|
|
|
|
} finally {
|
|
|
|
|
await connector.disconnect();
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 2. 트랜잭션 처리
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
```typescript
|
|
|
|
|
await transaction(async (client) => {
|
|
|
|
|
// 배치 상태 업데이트
|
2025-10-01 13:30:20 +09:00
|
|
|
await client.query(`UPDATE batch_jobs SET status = $1 WHERE id = $2`, [
|
|
|
|
|
"running",
|
|
|
|
|
batchId,
|
|
|
|
|
]);
|
2025-10-01 11:55:50 +09:00
|
|
|
|
|
|
|
|
// 실행 로그 생성
|
|
|
|
|
await client.query(
|
|
|
|
|
`INSERT INTO batch_execution_logs (batch_id, status, started_at)
|
|
|
|
|
VALUES ($1, $2, NOW())`,
|
|
|
|
|
[batchId, "running"]
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 3. Cron 표현식 처리
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
```typescript
|
|
|
|
|
import cron from "node-cron";
|
|
|
|
|
|
|
|
|
|
// Cron 표현식 검증
|
|
|
|
|
const isValid = cron.validate(cronExpression);
|
|
|
|
|
|
|
|
|
|
// 다음 실행 시간 계산
|
|
|
|
|
function calculateNextRun(cronExp: string): Date {
|
|
|
|
|
// Cron 파서를 사용하여 다음 실행 시간 계산
|
|
|
|
|
// ...
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 4. 대용량 데이터 처리
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
```typescript
|
|
|
|
|
// 스트리밍 방식으로 대용량 데이터 처리
|
|
|
|
|
const stream = await query<any>(
|
|
|
|
|
`SELECT * FROM large_table WHERE batch_id = $1`,
|
|
|
|
|
[batchId]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
for await (const row of stream) {
|
|
|
|
|
// 행 단위 처리
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 📝 전환 체크리스트
|
|
|
|
|
|
|
|
|
|
### BatchExternalDbService (8개)
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- [ ] `getExternalDbConnection()` - 연결 정보 조회
|
|
|
|
|
- [ ] `fetchDataFromExternalDb()` - 외부 DB 데이터 조회
|
|
|
|
|
- [ ] `saveDataToExternalDb()` - 외부 DB 데이터 저장
|
|
|
|
|
- [ ] `validateExternalDbConnection()` - 연결 검증
|
|
|
|
|
- [ ] `getExternalDbTables()` - 테이블 목록 조회
|
|
|
|
|
- [ ] `getExternalDbColumns()` - 컬럼 정보 조회
|
|
|
|
|
- [ ] `executeBatchQuery()` - 배치 쿼리 실행
|
|
|
|
|
- [ ] `getBatchExecutionStatus()` - 실행 상태 조회
|
|
|
|
|
|
|
|
|
|
### BatchExecutionLogService (7개)
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- [ ] `createExecutionLog()` - 실행 로그 생성
|
|
|
|
|
- [ ] `updateExecutionLog()` - 실행 로그 업데이트
|
|
|
|
|
- [ ] `getExecutionLogs()` - 실행 로그 목록 조회
|
|
|
|
|
- [ ] `getExecutionLogById()` - 실행 로그 단건 조회
|
|
|
|
|
- [ ] `getExecutionStats()` - 실행 통계 조회
|
|
|
|
|
- [ ] `cleanupOldLogs()` - 오래된 로그 삭제
|
|
|
|
|
- [ ] `getFailedExecutions()` - 실패한 실행 조회
|
|
|
|
|
|
|
|
|
|
### BatchManagementService (5개)
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- [ ] `getBatchJobs()` - 배치 작업 목록 조회
|
|
|
|
|
- [ ] `getBatchJob()` - 배치 작업 단건 조회
|
|
|
|
|
- [ ] `createBatchJob()` - 배치 작업 생성
|
|
|
|
|
- [ ] `updateBatchJob()` - 배치 작업 수정
|
|
|
|
|
- [ ] `deleteBatchJob()` - 배치 작업 삭제
|
|
|
|
|
|
|
|
|
|
### BatchSchedulerService (4개)
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- [ ] `getScheduledBatches()` - 스케줄된 배치 조회
|
|
|
|
|
- [ ] `createSchedule()` - 스케줄 생성
|
|
|
|
|
- [ ] `updateSchedule()` - 스케줄 수정
|
|
|
|
|
- [ ] `deleteSchedule()` - 스케줄 삭제
|
|
|
|
|
|
|
|
|
|
### 공통 작업
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- [ ] import 문 수정 (모든 서비스)
|
|
|
|
|
- [ ] Prisma import 완전 제거 (모든 서비스)
|
|
|
|
|
- [ ] 트랜잭션 로직 확인
|
|
|
|
|
- [ ] 에러 핸들링 검증
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 🧪 테스트 계획
|
|
|
|
|
|
|
|
|
|
### 단위 테스트 (24개)
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- 각 Prisma 호출별 1개씩
|
|
|
|
|
|
|
|
|
|
### 통합 테스트 (8개)
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- BatchExternalDbService: 외부 DB 연동 테스트 (2개)
|
|
|
|
|
- BatchExecutionLogService: 로그 생성 및 조회 테스트 (2개)
|
|
|
|
|
- BatchManagementService: 배치 작업 실행 테스트 (2개)
|
|
|
|
|
- BatchSchedulerService: 스케줄 실행 테스트 (2개)
|
|
|
|
|
|
|
|
|
|
### 성능 테스트
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- 대용량 데이터 처리 성능
|
|
|
|
|
- 동시 배치 실행 성능
|
|
|
|
|
- 외부 DB 연결 풀 성능
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 🎯 예상 난이도 및 소요 시간
|
|
|
|
|
|
|
|
|
|
- **난이도**: ⭐⭐⭐⭐⭐ (매우 높음)
|
|
|
|
|
- 외부 DB 연동
|
|
|
|
|
- 트랜잭션 처리
|
|
|
|
|
- 스케줄링 로직
|
|
|
|
|
- 대용량 데이터 처리
|
|
|
|
|
- **예상 소요 시간**: 4~5시간
|
|
|
|
|
- Phase 1 (BatchManagement + ExecutionLog): 1.5시간
|
|
|
|
|
- Phase 2 (Scheduler): 1시간
|
|
|
|
|
- Phase 3 (ExternalDb): 2시간
|
|
|
|
|
- 테스트 및 문서화: 0.5시간
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## ⚠️ 주의사항
|
|
|
|
|
|
|
|
|
|
### 중요 체크포인트
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
1. ✅ 외부 DB 연결은 반드시 try-finally에서 해제
|
|
|
|
|
2. ✅ 배치 실행 중 에러 시 롤백 처리
|
|
|
|
|
3. ✅ Cron 표현식 검증 필수
|
|
|
|
|
4. ✅ 대용량 데이터는 스트리밍 방식 사용
|
|
|
|
|
5. ✅ 동시 실행 제한 확인
|
|
|
|
|
|
|
|
|
|
### 성능 최적화
|
2025-10-01 13:30:20 +09:00
|
|
|
|
2025-10-01 11:55:50 +09:00
|
|
|
- 연결 풀 활용
|
|
|
|
|
- 배치 쿼리 최적화
|
|
|
|
|
- 인덱스 확인
|
|
|
|
|
- 불필요한 로그 제거
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
**상태**: ⏳ **대기 중**
|
|
|
|
|
**특이사항**: 외부 DB 연동, 스케줄링, 트랜잭션 처리 포함
|
|
|
|
|
**⚠️ 주의**: 배치 시스템의 핵심 기능이므로 신중한 테스트 필수!
|