From 67b45ea699eb58b93a427bfdc16d3bab818e6d35 Mon Sep 17 00:00:00 2001 From: kjs Date: Wed, 1 Oct 2025 11:55:50 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20Phase=203.15~3.16=20=ED=86=B5=ED=95=A9?= =?UTF-8?q?=20=EB=A7=88=EC=9D=B4=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EA=B3=84=ED=9A=8D=EC=84=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2개 주요 서비스 그룹에 대한 통합 전환 계획서 작성: 1. **Phase 3.15: Batch Services** (24개 호출) - 4개 배치 관련 서비스 통합 계획 - BatchExternalDbService (8개) - 외부 DB 연동 - BatchExecutionLogService (7개) - 실행 로그 - BatchManagementService (5개) - 배치 관리 - BatchSchedulerService (4개) - 스케줄러 주요 기술 요소: - 외부 DB 연결 및 쿼리 - 트랜잭션 처리 - Cron 표현식 스케줄링 - 대용량 데이터 처리 - 연결 풀 관리 2. **Phase 3.16: Data Management Services** (18개 호출) - 4개 데이터 관리 서비스 통합 계획 - EnhancedDynamicFormService (6개) - 고급 동적 폼 - DataMappingService (5개) - 데이터 매핑 - DataService (4개) - 동적 데이터 조회 - AdminService (3개) - 관리자 기능 주요 기술 요소: - 복잡한 JSON 필드 처리 - 동적 테이블 쿼리 (보안) - 재귀 CTE (계층 구조) - JSON 집계 쿼리 - SQL 인젝션 방지 각 통합 계획서 포함 내용: - 서비스별 상세 분석 - 통합 전환 전략 (Phase별) - 상세 전환 예시 (Before/After) - 기술적 고려사항 - 서비스별 체크리스트 - 통합 테스트 계획 - 예상 난이도 및 소요 시간 - 보안/성능 주의사항 메인 문서에 통합 계획서 링크 추가 서비스 그룹화로 가독성 향상 --- PHASE3.15_BATCH_SERVICES_MIGRATION.md | 409 ++++++++++++++++ ...3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md | 438 ++++++++++++++++++ PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md | 20 +- 3 files changed, 858 insertions(+), 9 deletions(-) create mode 100644 PHASE3.15_BATCH_SERVICES_MIGRATION.md create mode 100644 PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md diff --git a/PHASE3.15_BATCH_SERVICES_MIGRATION.md b/PHASE3.15_BATCH_SERVICES_MIGRATION.md new file mode 100644 index 00000000..7fbefec1 --- /dev/null +++ b/PHASE3.15_BATCH_SERVICES_MIGRATION.md @@ -0,0 +1,409 @@ +# 📋 Phase 3.15: Batch Services Raw Query 전환 계획 + +## 📋 개요 + +배치 관련 서비스들은 총 **24개의 Prisma 호출**이 있으며, 배치 작업 실행 및 관리를 담당합니다. + +### 📊 기본 정보 + +| 항목 | 내용 | +| --------------- | -------------------------------------------------------------- | +| 대상 서비스 | 4개 (BatchExternalDb, ExecutionLog, Management, Scheduler) | +| 파일 위치 | `backend-node/src/services/batch*.ts` | +| 총 파일 크기 | 2,161 라인 | +| Prisma 호출 | 24개 | +| **현재 진행률** | **0/24 (0%)** 🔄 **진행 예정** | +| 복잡도 | 높음 (외부 DB 연동, 스케줄링, 트랜잭션) | +| 우선순위 | 🔴 높음 (Phase 3.15) | +| **상태** | ⏳ **대기 중** | + +--- + +## 🔍 서비스별 상세 분석 + +### 1. BatchExternalDbService (8개 호출, 943 라인) + +**주요 기능**: +- 외부 DB에서 배치 데이터 조회 +- 외부 DB로 배치 데이터 저장 +- 외부 DB 연결 관리 +- 데이터 변환 및 매핑 + +**예상 Prisma 호출**: +- `getExternalDbConnection()` - 외부 DB 연결 정보 조회 +- `fetchDataFromExternalDb()` - 외부 DB 데이터 조회 +- `saveDataToExternalDb()` - 외부 DB 데이터 저장 +- `validateExternalDbConnection()` - 연결 검증 +- `getExternalDbTables()` - 테이블 목록 조회 +- `getExternalDbColumns()` - 컬럼 정보 조회 +- `executeBatchQuery()` - 배치 쿼리 실행 +- `getBatchExecutionStatus()` - 실행 상태 조회 + +**기술적 고려사항**: +- 다양한 DB 타입 지원 (PostgreSQL, MySQL, Oracle, MSSQL) +- 연결 풀 관리 +- 트랜잭션 처리 +- 에러 핸들링 및 재시도 + +--- + +### 2. BatchExecutionLogService (7개 호출, 299 라인) + +**주요 기능**: +- 배치 실행 로그 생성 +- 배치 실행 이력 조회 +- 배치 실행 통계 +- 로그 정리 + +**예상 Prisma 호출**: +- `createExecutionLog()` - 실행 로그 생성 +- `updateExecutionLog()` - 실행 로그 업데이트 +- `getExecutionLogs()` - 실행 로그 목록 조회 +- `getExecutionLogById()` - 실행 로그 단건 조회 +- `getExecutionStats()` - 실행 통계 조회 +- `cleanupOldLogs()` - 오래된 로그 삭제 +- `getFailedExecutions()` - 실패한 실행 조회 + +**기술적 고려사항**: +- 대용량 로그 처리 +- 통계 쿼리 최적화 +- 로그 보관 정책 +- 페이징 및 필터링 + +--- + +### 3. BatchManagementService (5개 호출, 373 라인) + +**주요 기능**: +- 배치 작업 설정 관리 +- 배치 작업 실행 +- 배치 작업 중지 +- 배치 작업 모니터링 + +**예상 Prisma 호출**: +- `getBatchJobs()` - 배치 작업 목록 조회 +- `getBatchJob()` - 배치 작업 단건 조회 +- `createBatchJob()` - 배치 작업 생성 +- `updateBatchJob()` - 배치 작업 수정 +- `deleteBatchJob()` - 배치 작업 삭제 + +**기술적 고려사항**: +- JSON 설정 필드 (job_config) +- 작업 상태 관리 +- 동시 실행 제어 +- 의존성 관리 + +--- + +### 4. BatchSchedulerService (4개 호출, 546 라인) + +**주요 기능**: +- 배치 스케줄 설정 +- Cron 표현식 관리 +- 스케줄 실행 +- 다음 실행 시간 계산 + +**예상 Prisma 호출**: +- `getScheduledBatches()` - 스케줄된 배치 조회 +- `createSchedule()` - 스케줄 생성 +- `updateSchedule()` - 스케줄 수정 +- `deleteSchedule()` - 스케줄 삭제 + +**기술적 고려사항**: +- Cron 표현식 파싱 +- 시간대 처리 +- 실행 이력 추적 +- 스케줄 충돌 방지 + +--- + +## 💡 통합 전환 전략 + +### Phase 1: 핵심 서비스 전환 (12개) +**BatchManagementService (5개) + BatchExecutionLogService (7개)** +- 배치 관리 및 로깅 기능 우선 +- 상대적으로 단순한 CRUD + +### Phase 2: 스케줄러 전환 (4개) +**BatchSchedulerService (4개)** +- 스케줄 관리 +- Cron 표현식 처리 + +### Phase 3: 외부 DB 연동 전환 (8개) +**BatchExternalDbService (8개)** +- 가장 복잡한 서비스 +- 외부 DB 연결 및 쿼리 + +--- + +## 💻 전환 예시 + +### 예시 1: 배치 실행 로그 생성 + +**변경 전**: +```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, + }, +}); +``` + +**변경 후**: +```typescript +const log = await queryOne( + `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: 배치 통계 조회 + +**변경 전**: +```typescript +const stats = await prisma.batch_execution_logs.groupBy({ + by: ["status"], + where: { + batch_id: batchId, + started_at: { gte: startDate, lte: endDate }, + }, + _count: { id: true }, +}); +``` + +**변경 후**: +```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 연결 및 쿼리 + +**변경 전**: +```typescript +// 연결 정보 조회 +const connection = await prisma.external_db_connections.findUnique({ + where: { id: connectionId }, +}); + +// 외부 DB 쿼리 실행 (Prisma 사용 불가, 이미 Raw Query일 가능성) +const externalData = await externalDbClient.query(sql); +``` + +**변경 후**: +```typescript +// 연결 정보 조회 +const connection = await queryOne( + `SELECT * FROM external_db_connections WHERE id = $1`, + [connectionId] +); + +// 외부 DB 쿼리 실행 (기존 로직 유지) +const externalData = await externalDbClient.query(sql); +``` + +### 예시 4: 스케줄 관리 + +**변경 전**: +```typescript +const schedule = await prisma.batch_schedules.create({ + data: { + batch_id: batchId, + cron_expression: cronExp, + is_active: true, + next_run_at: calculateNextRun(cronExp), + }, +}); +``` + +**변경 후**: +```typescript +const nextRun = calculateNextRun(cronExp); + +const schedule = await queryOne( + `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 연결 관리 +```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. 트랜잭션 처리 +```typescript +await transaction(async (client) => { + // 배치 상태 업데이트 + await client.query( + `UPDATE batch_jobs SET status = $1 WHERE id = $2`, + ["running", batchId] + ); + + // 실행 로그 생성 + await client.query( + `INSERT INTO batch_execution_logs (batch_id, status, started_at) + VALUES ($1, $2, NOW())`, + [batchId, "running"] + ); +}); +``` + +### 3. Cron 표현식 처리 +```typescript +import cron from "node-cron"; + +// Cron 표현식 검증 +const isValid = cron.validate(cronExpression); + +// 다음 실행 시간 계산 +function calculateNextRun(cronExp: string): Date { + // Cron 파서를 사용하여 다음 실행 시간 계산 + // ... +} +``` + +### 4. 대용량 데이터 처리 +```typescript +// 스트리밍 방식으로 대용량 데이터 처리 +const stream = await query( + `SELECT * FROM large_table WHERE batch_id = $1`, + [batchId] +); + +for await (const row of stream) { + // 행 단위 처리 +} +``` + +--- + +## 📝 전환 체크리스트 + +### BatchExternalDbService (8개) +- [ ] `getExternalDbConnection()` - 연결 정보 조회 +- [ ] `fetchDataFromExternalDb()` - 외부 DB 데이터 조회 +- [ ] `saveDataToExternalDb()` - 외부 DB 데이터 저장 +- [ ] `validateExternalDbConnection()` - 연결 검증 +- [ ] `getExternalDbTables()` - 테이블 목록 조회 +- [ ] `getExternalDbColumns()` - 컬럼 정보 조회 +- [ ] `executeBatchQuery()` - 배치 쿼리 실행 +- [ ] `getBatchExecutionStatus()` - 실행 상태 조회 + +### BatchExecutionLogService (7개) +- [ ] `createExecutionLog()` - 실행 로그 생성 +- [ ] `updateExecutionLog()` - 실행 로그 업데이트 +- [ ] `getExecutionLogs()` - 실행 로그 목록 조회 +- [ ] `getExecutionLogById()` - 실행 로그 단건 조회 +- [ ] `getExecutionStats()` - 실행 통계 조회 +- [ ] `cleanupOldLogs()` - 오래된 로그 삭제 +- [ ] `getFailedExecutions()` - 실패한 실행 조회 + +### BatchManagementService (5개) +- [ ] `getBatchJobs()` - 배치 작업 목록 조회 +- [ ] `getBatchJob()` - 배치 작업 단건 조회 +- [ ] `createBatchJob()` - 배치 작업 생성 +- [ ] `updateBatchJob()` - 배치 작업 수정 +- [ ] `deleteBatchJob()` - 배치 작업 삭제 + +### BatchSchedulerService (4개) +- [ ] `getScheduledBatches()` - 스케줄된 배치 조회 +- [ ] `createSchedule()` - 스케줄 생성 +- [ ] `updateSchedule()` - 스케줄 수정 +- [ ] `deleteSchedule()` - 스케줄 삭제 + +### 공통 작업 +- [ ] import 문 수정 (모든 서비스) +- [ ] Prisma import 완전 제거 (모든 서비스) +- [ ] 트랜잭션 로직 확인 +- [ ] 에러 핸들링 검증 + +--- + +## 🧪 테스트 계획 + +### 단위 테스트 (24개) +- 각 Prisma 호출별 1개씩 + +### 통합 테스트 (8개) +- BatchExternalDbService: 외부 DB 연동 테스트 (2개) +- BatchExecutionLogService: 로그 생성 및 조회 테스트 (2개) +- BatchManagementService: 배치 작업 실행 테스트 (2개) +- BatchSchedulerService: 스케줄 실행 테스트 (2개) + +### 성능 테스트 +- 대용량 데이터 처리 성능 +- 동시 배치 실행 성능 +- 외부 DB 연결 풀 성능 + +--- + +## 🎯 예상 난이도 및 소요 시간 + +- **난이도**: ⭐⭐⭐⭐⭐ (매우 높음) + - 외부 DB 연동 + - 트랜잭션 처리 + - 스케줄링 로직 + - 대용량 데이터 처리 + +- **예상 소요 시간**: 4~5시간 + - Phase 1 (BatchManagement + ExecutionLog): 1.5시간 + - Phase 2 (Scheduler): 1시간 + - Phase 3 (ExternalDb): 2시간 + - 테스트 및 문서화: 0.5시간 + +--- + +## ⚠️ 주의사항 + +### 중요 체크포인트 +1. ✅ 외부 DB 연결은 반드시 try-finally에서 해제 +2. ✅ 배치 실행 중 에러 시 롤백 처리 +3. ✅ Cron 표현식 검증 필수 +4. ✅ 대용량 데이터는 스트리밍 방식 사용 +5. ✅ 동시 실행 제한 확인 + +### 성능 최적화 +- 연결 풀 활용 +- 배치 쿼리 최적화 +- 인덱스 확인 +- 불필요한 로그 제거 + +--- + +**상태**: ⏳ **대기 중** +**특이사항**: 외부 DB 연동, 스케줄링, 트랜잭션 처리 포함 +**⚠️ 주의**: 배치 시스템의 핵심 기능이므로 신중한 테스트 필수! + diff --git a/PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md b/PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md new file mode 100644 index 00000000..457e0dd4 --- /dev/null +++ b/PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md @@ -0,0 +1,438 @@ +# 📋 Phase 3.16: Data Management Services Raw Query 전환 계획 + +## 📋 개요 + +데이터 관리 관련 서비스들은 총 **18개의 Prisma 호출**이 있으며, 동적 폼, 데이터 매핑, 데이터 서비스, 관리자 기능을 담당합니다. + +### 📊 기본 정보 + +| 항목 | 내용 | +| --------------- | ------------------------------------------------------------------------- | +| 대상 서비스 | 4개 (EnhancedDynamicForm, DataMapping, Data, Admin) | +| 파일 위치 | `backend-node/src/services/{enhanced,data,admin}*.ts` | +| 총 파일 크기 | 2,062 라인 | +| Prisma 호출 | 18개 | +| **현재 진행률** | **0/18 (0%)** 🔄 **진행 예정** | +| 복잡도 | 중간 (동적 쿼리, JSON 필드, 관리자 기능) | +| 우선순위 | 🟡 중간 (Phase 3.16) | +| **상태** | ⏳ **대기 중** | + +--- + +## 🔍 서비스별 상세 분석 + +### 1. EnhancedDynamicFormService (6개 호출, 786 라인) + +**주요 기능**: +- 고급 동적 폼 관리 +- 폼 검증 규칙 +- 조건부 필드 표시 +- 폼 템플릿 관리 + +**예상 Prisma 호출**: +- `getEnhancedForms()` - 고급 폼 목록 조회 +- `getEnhancedForm()` - 고급 폼 단건 조회 +- `createEnhancedForm()` - 고급 폼 생성 +- `updateEnhancedForm()` - 고급 폼 수정 +- `deleteEnhancedForm()` - 고급 폼 삭제 +- `getFormValidationRules()` - 검증 규칙 조회 + +**기술적 고려사항**: +- JSON 필드 (validation_rules, conditional_logic, field_config) +- 복잡한 검증 규칙 +- 동적 필드 생성 +- 조건부 표시 로직 + +--- + +### 2. DataMappingService (5개 호출, 575 라인) + +**주요 기능**: +- 데이터 매핑 설정 관리 +- 소스-타겟 필드 매핑 +- 데이터 변환 규칙 +- 매핑 실행 + +**예상 Prisma 호출**: +- `getDataMappings()` - 매핑 설정 목록 조회 +- `getDataMapping()` - 매핑 설정 단건 조회 +- `createDataMapping()` - 매핑 설정 생성 +- `updateDataMapping()` - 매핑 설정 수정 +- `deleteDataMapping()` - 매핑 설정 삭제 + +**기술적 고려사항**: +- JSON 필드 (field_mappings, transformation_rules) +- 복잡한 변환 로직 +- 매핑 검증 +- 실행 이력 추적 + +--- + +### 3. DataService (4개 호출, 327 라인) + +**주요 기능**: +- 동적 데이터 조회 +- 데이터 필터링 +- 데이터 정렬 +- 데이터 집계 + +**예상 Prisma 호출**: +- `getDataByTable()` - 테이블별 데이터 조회 +- `getDataById()` - 데이터 단건 조회 +- `executeCustomQuery()` - 커스텀 쿼리 실행 +- `getDataStatistics()` - 데이터 통계 조회 + +**기술적 고려사항**: +- 동적 테이블 쿼리 +- SQL 인젝션 방지 +- 동적 WHERE 조건 +- 집계 쿼리 + +--- + +### 4. AdminService (3개 호출, 374 라인) + +**주요 기능**: +- 관리자 메뉴 관리 +- 시스템 설정 +- 사용자 관리 +- 로그 조회 + +**예상 Prisma 호출**: +- `getAdminMenus()` - 관리자 메뉴 조회 +- `getSystemSettings()` - 시스템 설정 조회 +- `updateSystemSettings()` - 시스템 설정 업데이트 + +**기술적 고려사항**: +- 메뉴 계층 구조 +- 권한 기반 필터링 +- JSON 설정 필드 +- 캐싱 + +--- + +## 💡 통합 전환 전략 + +### Phase 1: 단순 CRUD 전환 (12개) +**EnhancedDynamicFormService (6개) + DataMappingService (5개) + AdminService (1개)** +- 기본 CRUD 기능 +- JSON 필드 처리 + +### Phase 2: 동적 쿼리 전환 (4개) +**DataService (4개)** +- 동적 테이블 쿼리 +- 보안 검증 + +### Phase 3: 고급 기능 전환 (2개) +**AdminService (2개)** +- 시스템 설정 +- 캐싱 + +--- + +## 💻 전환 예시 + +### 예시 1: 고급 폼 생성 (JSON 필드) + +**변경 전**: +```typescript +const form = await prisma.enhanced_forms.create({ + data: { + form_code: formCode, + form_name: formName, + validation_rules: validationRules, // JSON + conditional_logic: conditionalLogic, // JSON + field_config: fieldConfig, // JSON + company_code: companyCode, + }, +}); +``` + +**변경 후**: +```typescript +const form = await queryOne( + `INSERT INTO enhanced_forms + (form_code, form_name, validation_rules, conditional_logic, + field_config, company_code, created_at, updated_at) + VALUES ($1, $2, $3, $4, $5, $6, NOW(), NOW()) + RETURNING *`, + [ + formCode, + formName, + JSON.stringify(validationRules), + JSON.stringify(conditionalLogic), + JSON.stringify(fieldConfig), + companyCode, + ] +); +``` + +### 예시 2: 데이터 매핑 조회 + +**변경 전**: +```typescript +const mappings = await prisma.data_mappings.findMany({ + where: { + source_table: sourceTable, + target_table: targetTable, + is_active: true, + }, + include: { + source_columns: true, + target_columns: true, + }, +}); +``` + +**변경 후**: +```typescript +const mappings = await query( + `SELECT + dm.*, + json_agg(DISTINCT jsonb_build_object( + 'column_id', sc.column_id, + 'column_name', sc.column_name + )) FILTER (WHERE sc.column_id IS NOT NULL) as source_columns, + json_agg(DISTINCT jsonb_build_object( + 'column_id', tc.column_id, + 'column_name', tc.column_name + )) FILTER (WHERE tc.column_id IS NOT NULL) as target_columns + FROM data_mappings dm + LEFT JOIN columns sc ON dm.mapping_id = sc.mapping_id AND sc.type = 'source' + LEFT JOIN columns tc ON dm.mapping_id = tc.mapping_id AND tc.type = 'target' + WHERE dm.source_table = $1 + AND dm.target_table = $2 + AND dm.is_active = $3 + GROUP BY dm.mapping_id`, + [sourceTable, targetTable, true] +); +``` + +### 예시 3: 동적 테이블 쿼리 (DataService) + +**변경 전**: +```typescript +// Prisma로는 동적 테이블 쿼리 불가능 +// 이미 $queryRawUnsafe 사용 중일 가능성 +const data = await prisma.$queryRawUnsafe( + `SELECT * FROM ${tableName} WHERE ${whereClause}`, + ...params +); +``` + +**변경 후**: +```typescript +// SQL 인젝션 방지를 위한 테이블명 검증 +const validTableName = validateTableName(tableName); + +const data = await query( + `SELECT * FROM ${validTableName} WHERE ${whereClause}`, + params +); +``` + +### 예시 4: 관리자 메뉴 조회 (계층 구조) + +**변경 전**: +```typescript +const menus = await prisma.admin_menus.findMany({ + where: { is_active: true }, + orderBy: { sort_order: "asc" }, + include: { + children: { + orderBy: { sort_order: "asc" }, + }, + }, +}); +``` + +**변경 후**: +```typescript +// 재귀 CTE를 사용한 계층 쿼리 +const menus = await query( + `WITH RECURSIVE menu_tree AS ( + SELECT *, 0 as level, ARRAY[menu_id] as path + FROM admin_menus + WHERE parent_id IS NULL AND is_active = $1 + + UNION ALL + + SELECT m.*, mt.level + 1, mt.path || m.menu_id + FROM admin_menus m + JOIN menu_tree mt ON m.parent_id = mt.menu_id + WHERE m.is_active = $1 + ) + SELECT * FROM menu_tree + ORDER BY path, sort_order`, + [true] +); +``` + +--- + +## 🔧 기술적 고려사항 + +### 1. JSON 필드 처리 +```typescript +// 복잡한 JSON 구조 +interface ValidationRules { + required?: string[]; + min?: Record; + max?: Record; + pattern?: Record; + custom?: Array<{ field: string; rule: string }>; +} + +// 저장 시 +JSON.stringify(validationRules); + +// 조회 후 +const parsed = typeof row.validation_rules === "string" + ? JSON.parse(row.validation_rules) + : row.validation_rules; +``` + +### 2. 동적 테이블 쿼리 보안 +```typescript +// 테이블명 화이트리스트 +const ALLOWED_TABLES = ["users", "products", "orders"]; + +function validateTableName(tableName: string): string { + if (!ALLOWED_TABLES.includes(tableName)) { + throw new Error("Invalid table name"); + } + return tableName; +} + +// 컬럼명 검증 +function validateColumnName(columnName: string): string { + if (!/^[a-z_][a-z0-9_]*$/i.test(columnName)) { + throw new Error("Invalid column name"); + } + return columnName; +} +``` + +### 3. 재귀 CTE (계층 구조) +```sql +WITH RECURSIVE hierarchy AS ( + -- 최상위 노드 + SELECT * FROM table WHERE parent_id IS NULL + + UNION ALL + + -- 하위 노드 + SELECT t.* FROM table t + JOIN hierarchy h ON t.parent_id = h.id +) +SELECT * FROM hierarchy +``` + +### 4. JSON 집계 (관계 데이터) +```sql +SELECT + parent.*, + COALESCE( + json_agg( + jsonb_build_object('id', child.id, 'name', child.name) + ) FILTER (WHERE child.id IS NOT NULL), + '[]' + ) as children +FROM parent +LEFT JOIN child ON parent.id = child.parent_id +GROUP BY parent.id +``` + +--- + +## 📝 전환 체크리스트 + +### EnhancedDynamicFormService (6개) +- [ ] `getEnhancedForms()` - 목록 조회 +- [ ] `getEnhancedForm()` - 단건 조회 +- [ ] `createEnhancedForm()` - 생성 (JSON 필드) +- [ ] `updateEnhancedForm()` - 수정 (JSON 필드) +- [ ] `deleteEnhancedForm()` - 삭제 +- [ ] `getFormValidationRules()` - 검증 규칙 조회 + +### DataMappingService (5개) +- [ ] `getDataMappings()` - 목록 조회 +- [ ] `getDataMapping()` - 단건 조회 +- [ ] `createDataMapping()` - 생성 +- [ ] `updateDataMapping()` - 수정 +- [ ] `deleteDataMapping()` - 삭제 + +### DataService (4개) +- [ ] `getDataByTable()` - 동적 테이블 조회 +- [ ] `getDataById()` - 단건 조회 +- [ ] `executeCustomQuery()` - 커스텀 쿼리 +- [ ] `getDataStatistics()` - 통계 조회 + +### AdminService (3개) +- [ ] `getAdminMenus()` - 메뉴 조회 (재귀 CTE) +- [ ] `getSystemSettings()` - 시스템 설정 조회 +- [ ] `updateSystemSettings()` - 시스템 설정 업데이트 + +### 공통 작업 +- [ ] import 문 수정 (모든 서비스) +- [ ] Prisma import 완전 제거 +- [ ] JSON 필드 처리 확인 +- [ ] 보안 검증 (SQL 인젝션) + +--- + +## 🧪 테스트 계획 + +### 단위 테스트 (18개) +- 각 Prisma 호출별 1개씩 + +### 통합 테스트 (6개) +- EnhancedDynamicFormService: 폼 생성 및 검증 테스트 (2개) +- DataMappingService: 매핑 설정 및 실행 테스트 (2개) +- DataService: 동적 쿼리 및 보안 테스트 (1개) +- AdminService: 메뉴 계층 구조 테스트 (1개) + +### 보안 테스트 +- SQL 인젝션 방지 테스트 +- 테이블명 검증 테스트 +- 컬럼명 검증 테스트 + +--- + +## 🎯 예상 난이도 및 소요 시간 + +- **난이도**: ⭐⭐⭐⭐ (높음) + - JSON 필드 처리 + - 동적 쿼리 보안 + - 재귀 CTE + - JSON 집계 + +- **예상 소요 시간**: 2.5~3시간 + - Phase 1 (기본 CRUD): 1시간 + - Phase 2 (동적 쿼리): 1시간 + - Phase 3 (고급 기능): 0.5시간 + - 테스트 및 문서화: 0.5시간 + +--- + +## ⚠️ 주의사항 + +### 보안 필수 체크리스트 +1. ✅ 동적 테이블명은 반드시 화이트리스트 검증 +2. ✅ 동적 컬럼명은 정규식으로 검증 +3. ✅ WHERE 절 파라미터는 반드시 바인딩 +4. ✅ JSON 필드는 파싱 에러 처리 +5. ✅ 재귀 쿼리는 깊이 제한 설정 + +### 성능 최적화 +- JSON 필드 인덱싱 (GIN 인덱스) +- 재귀 쿼리 깊이 제한 +- 집계 쿼리 최적화 +- 필요시 캐싱 적용 + +--- + +**상태**: ⏳ **대기 중** +**특이사항**: JSON 필드, 동적 쿼리, 재귀 CTE, 보안 검증 포함 +**⚠️ 주의**: 동적 쿼리는 SQL 인젝션 방지가 매우 중요! + diff --git a/PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md b/PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md index 7d0e3176..e458899a 100644 --- a/PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md +++ b/PRISMA_TO_RAW_QUERY_MIGRATION_PLAN.md @@ -137,17 +137,19 @@ backend-node/ (루트) - `ddlAuditLogger.ts` (8개) - DDL 감사 로그 - [계획서](PHASE3.11_DDL_AUDIT_LOGGER_MIGRATION.md) - `externalCallConfigService.ts` (8개) - 외부 호출 설정 - [계획서](PHASE3.12_EXTERNAL_CALL_CONFIG_SERVICE_MIGRATION.md) -- `batchExternalDbService.ts` (8개) - 배치 외부DB ⭐ 신규 발견 -- `batchExecutionLogService.ts` (7개) - 배치 실행 로그 ⭐ 신규 발견 -- `enhancedDynamicFormService.ts` (6개) - 확장 동적 폼 ⭐ 신규 발견 -- `ddlExecutionService.ts` (6개) - DDL 실행 (이미 전환 완료?) - `entityJoinService.ts` (5개) - 엔티티 조인 - [계획서](PHASE3.13_ENTITY_JOIN_SERVICE_MIGRATION.md) -- `dataMappingService.ts` (5개) - 데이터 매핑 ⭐ 신규 발견 -- `batchManagementService.ts` (5개) - 배치 관리 ⭐ 신규 발견 - `authService.ts` (5개) - 사용자 인증 - [계획서](PHASE3.14_AUTH_SERVICE_MIGRATION.md) -- `batchSchedulerService.ts` (4개) - 배치 스케줄러 ⭐ 신규 발견 -- `dataService.ts` (4개) - 데이터 서비스 ⭐ 신규 발견 -- `adminService.ts` (3개) - 관리자 메뉴 +- **배치 관련 서비스 (24개)** - [통합 계획서](PHASE3.15_BATCH_SERVICES_MIGRATION.md) + - `batchExternalDbService.ts` (8개) - 배치 외부DB + - `batchExecutionLogService.ts` (7개) - 배치 실행 로그 + - `batchManagementService.ts` (5개) - 배치 관리 + - `batchSchedulerService.ts` (4개) - 배치 스케줄러 +- **데이터 관리 서비스 (18개)** - [통합 계획서](PHASE3.16_DATA_MANAGEMENT_SERVICES_MIGRATION.md) + - `enhancedDynamicFormService.ts` (6개) - 확장 동적 폼 + - `dataMappingService.ts` (5개) - 데이터 매핑 + - `dataService.ts` (4개) - 데이터 서비스 + - `adminService.ts` (3개) - 관리자 메뉴 +- `ddlExecutionService.ts` (6개) - DDL 실행 (이미 전환 완료?) - `referenceCacheService.ts` (3개) - 캐시 관리 #### 🟢 **단순 (컨트롤러 레이어) - 4순위**