feat: Phase 2.5 & 2.6 완료 - ExternalDbConnectionService + DataflowControlService Raw Query 전환
Phase 2.5: ExternalDbConnectionService (15개) - 15개 Prisma 호출을 모두 Raw Query로 전환 - 동적 WHERE 조건 생성 및 동적 UPDATE 쿼리 구현 - 비밀번호 암호화/복호화 로직 유지 - ILIKE 검색 지원 Phase 2.6: DataflowControlService (6개) - 6개 Prisma 호출을 모두 Raw Query로 전환 - 파라미터 바인딩 수정 (MySQL ? → PostgreSQL $1, $2) - 복잡한 비즈니스 로직 및 다중 커넥션 지원 유지 - 조건부 실행, 에러 처리 로직 보존 전체 성과: - TypeScript 컴파일 성공 (linter 에러 0개) - Prisma import 완전 제거 - Phase 2 진행률: 152/162 (93.8%) - 전체 진행률: 238/444 (53.6%)
This commit is contained in:
parent
5f3f869135
commit
e5180b7659
|
|
@ -9,11 +9,12 @@ DataflowControlService는 **6개의 Prisma 호출**이 있으며, 데이터플
|
|||
| 항목 | 내용 |
|
||||
| --------------- | ----------------------------------------------------- |
|
||||
| 파일 위치 | `backend-node/src/services/dataflowControlService.ts` |
|
||||
| 파일 크기 | 600+ 라인 |
|
||||
| Prisma 호출 | 6개 |
|
||||
| **현재 진행률** | **0/6 (0%)** ⏳ **진행 예정** |
|
||||
| 파일 크기 | 1,100+ 라인 |
|
||||
| Prisma 호출 | 0개 (전환 완료) |
|
||||
| **현재 진행률** | **6/6 (100%)** ✅ **완료** |
|
||||
| 복잡도 | 높음 (복잡한 비즈니스 로직) |
|
||||
| 우선순위 | 🟡 중간 (Phase 2.6) |
|
||||
| **상태** | ✅ **전환 완료 및 컴파일 성공** |
|
||||
|
||||
### 🎯 전환 목표
|
||||
|
||||
|
|
@ -163,16 +164,34 @@ await transaction(async (client) => {
|
|||
|
||||
---
|
||||
|
||||
## 📋 전환 완료 내역
|
||||
|
||||
### ✅ 전환된 함수들 (6개 Prisma 호출)
|
||||
|
||||
1. **executeDataflowControl()** - 관계도 정보 조회 (findUnique → queryOne)
|
||||
2. **evaluateActionConditions()** - 대상 테이블 조건 확인 ($queryRawUnsafe → query)
|
||||
3. **executeInsertAction()** - INSERT 실행 ($executeRawUnsafe → query)
|
||||
4. **executeUpdateAction()** - UPDATE 실행 ($executeRawUnsafe → query)
|
||||
5. **executeDeleteAction()** - DELETE 실행 ($executeRawUnsafe → query)
|
||||
6. **checkColumnExists()** - 컬럼 존재 확인 ($queryRawUnsafe → query)
|
||||
|
||||
### 🔧 주요 기술적 해결 사항
|
||||
|
||||
1. **Prisma import 완전 제거**: `import { query, queryOne } from "../database/db"`
|
||||
2. **동적 테이블 쿼리 전환**: `$queryRawUnsafe` / `$executeRawUnsafe` → `query()`
|
||||
3. **파라미터 바인딩 수정**: MySQL `?` → PostgreSQL `$1, $2...`
|
||||
4. **복잡한 비즈니스 로직 유지**: 조건부 실행, 다중 커넥션, 에러 처리
|
||||
|
||||
## 🎯 완료 기준
|
||||
|
||||
- [ ] **6개 모든 Prisma 호출을 Raw Query로 전환 완료**
|
||||
- [ ] **모든 TypeScript 컴파일 오류 해결**
|
||||
- [ ] **트랜잭션 정상 동작 확인**
|
||||
- [ ] **복잡한 비즈니스 로직 정상 동작**
|
||||
- [ ] **모든 단위 테스트 통과 (10개)**
|
||||
- [ ] **모든 통합 테스트 작성 완료 (4개 시나리오)**
|
||||
- [ ] **`import prisma` 완전 제거 및 `import { query, transaction } from "../database/db"` 사용**
|
||||
- [ ] **성능 저하 없음**
|
||||
- [x] **6개 모든 Prisma 호출을 Raw Query로 전환 완료** ✅
|
||||
- [x] **모든 TypeScript 컴파일 오류 해결** ✅
|
||||
- [x] **`import prisma` 완전 제거** ✅
|
||||
- [ ] **트랜잭션 정상 동작 확인** ⏳
|
||||
- [ ] **복잡한 비즈니스 로직 정상 동작** ⏳
|
||||
- [ ] **모든 단위 테스트 통과 (10개)** ⏳
|
||||
- [ ] **모든 통합 테스트 작성 완료 (4개 시나리오)** ⏳
|
||||
- [ ] **성능 저하 없음** ⏳
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -198,8 +217,9 @@ await transaction(async (client) => {
|
|||
---
|
||||
|
||||
**작성일**: 2025-09-30
|
||||
**예상 소요 시간**: 1일
|
||||
**완료일**: 2025-10-01
|
||||
**소요 시간**: 30분
|
||||
**담당자**: 백엔드 개발팀
|
||||
**우선순위**: 🟡 중간 (Phase 2.6)
|
||||
**상태**: ⏳ **진행 예정**
|
||||
**상태**: ✅ **전환 완료** (테스트 필요)
|
||||
**특이사항**: 복잡한 비즈니스 로직이 포함되어 있어 신중한 테스트 필요
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ backend-node/src/services/
|
|||
├── dataflowService.ts # 데이터플로우 (0개 호출) ✅ 전환 완료
|
||||
├── dynamicFormService.ts # 동적 폼 (15개 호출)
|
||||
├── externalDbConnectionService.ts # 외부DB (0개 호출) ✅ 전환 완료
|
||||
├── dataflowControlService.ts # 제어관리 (6개 호출)
|
||||
├── dataflowControlService.ts # 제어관리 (0개 호출) ✅ 전환 완료
|
||||
├── ddlExecutionService.ts # DDL 실행 (6개 호출)
|
||||
├── authService.ts # 인증 (5개 호출)
|
||||
└── multiConnectionQueryService.ts # 다중 연결 (4개 호출)
|
||||
|
|
@ -115,7 +115,7 @@ backend-node/ (루트)
|
|||
- `dataflowService.ts` (0개) - ✅ **전환 완료** (Phase 2.3)
|
||||
- `dynamicFormService.ts` (15개) - UPSERT 및 동적 테이블 처리
|
||||
- `externalDbConnectionService.ts` (0개) - ✅ **전환 완료** (Phase 2.5)
|
||||
- `dataflowControlService.ts` (6개) - 복잡한 제어 로직
|
||||
- `dataflowControlService.ts` (0개) - ✅ **전환 완료** (Phase 2.6)
|
||||
- `enhancedDataflowControlService.ts` (0개) - 다중 연결 제어 (Raw Query만 사용)
|
||||
- `multiConnectionQueryService.ts` (4개) - 외부 DB 연결
|
||||
|
||||
|
|
@ -1110,8 +1110,12 @@ describe("Performance Benchmarks", () => {
|
|||
- [x] TypeScript 컴파일 성공
|
||||
- [x] Prisma import 완전 제거
|
||||
- 📄 **[PHASE2.5_EXTERNAL_DB_CONNECTION_MIGRATION.md](PHASE2.5_EXTERNAL_DB_CONNECTION_MIGRATION.md)**
|
||||
- [ ] **DataflowControlService 전환 (6개)** - Phase 2.6 🟡 중간 우선순위
|
||||
- 6개 Prisma 호출 (복잡한 비즈니스 로직)
|
||||
- [x] **DataflowControlService 전환 (6개)** ✅ **완료** (Phase 2.6)
|
||||
- [x] 6개 Prisma 호출 전환 완료 (데이터플로우 제어 + 동적 테이블 CRUD)
|
||||
- [x] 파라미터 바인딩 수정 (MySQL → PostgreSQL 스타일)
|
||||
- [x] 복잡한 비즈니스 로직 유지
|
||||
- [x] TypeScript 컴파일 성공
|
||||
- [x] Prisma import 완전 제거
|
||||
- 📄 **[PHASE2.6_DATAFLOW_CONTROL_MIGRATION.md](PHASE2.6_DATAFLOW_CONTROL_MIGRATION.md)**
|
||||
|
||||
#### ✅ 다른 Phase로 이동
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
// 🔧 Prisma 클라이언트 중복 생성 방지 - 기존 인스턴스 재사용
|
||||
import prisma = require("../config/database");
|
||||
import { query, queryOne } from "../database/db";
|
||||
|
||||
export interface ControlCondition {
|
||||
id: string;
|
||||
|
|
@ -82,9 +81,10 @@ export class DataflowControlService {
|
|||
});
|
||||
|
||||
// 관계도 정보 조회
|
||||
const diagram = await prisma.dataflow_diagrams.findUnique({
|
||||
where: { diagram_id: diagramId },
|
||||
});
|
||||
const diagram = await queryOne<any>(
|
||||
`SELECT * FROM dataflow_diagrams WHERE diagram_id = $1`,
|
||||
[diagramId]
|
||||
);
|
||||
|
||||
if (!diagram) {
|
||||
return {
|
||||
|
|
@ -527,9 +527,9 @@ export class DataflowControlService {
|
|||
}
|
||||
|
||||
// 대상 테이블에서 조건에 맞는 데이터 조회
|
||||
const queryResult = await prisma.$queryRawUnsafe(
|
||||
const queryResult = await query<Record<string, any>>(
|
||||
`SELECT ${condition.field} FROM ${tableName} WHERE ${condition.field} = $1 LIMIT 1`,
|
||||
condition.value
|
||||
[condition.value]
|
||||
);
|
||||
|
||||
dataToCheck =
|
||||
|
|
@ -758,14 +758,14 @@ export class DataflowControlService {
|
|||
|
||||
try {
|
||||
// 동적 테이블 INSERT 실행
|
||||
const result = await prisma.$executeRawUnsafe(
|
||||
`
|
||||
INSERT INTO ${targetTable} (${Object.keys(insertData).join(", ")})
|
||||
VALUES (${Object.keys(insertData)
|
||||
.map(() => "?")
|
||||
.join(", ")})
|
||||
`,
|
||||
...Object.values(insertData)
|
||||
const placeholders = Object.keys(insertData)
|
||||
.map((_, i) => `$${i + 1}`)
|
||||
.join(", ");
|
||||
|
||||
const result = await query(
|
||||
`INSERT INTO ${targetTable} (${Object.keys(insertData).join(", ")})
|
||||
VALUES (${placeholders})`,
|
||||
Object.values(insertData)
|
||||
);
|
||||
|
||||
results.push({
|
||||
|
|
@ -878,10 +878,7 @@ export class DataflowControlService {
|
|||
);
|
||||
console.log(`📊 쿼리 파라미터:`, allValues);
|
||||
|
||||
const result = await prisma.$executeRawUnsafe(
|
||||
updateQuery,
|
||||
...allValues
|
||||
);
|
||||
const result = await query(updateQuery, allValues);
|
||||
|
||||
console.log(
|
||||
`✅ UPDATE 성공 (${i + 1}/${action.fieldMappings.length}):`,
|
||||
|
|
@ -1033,10 +1030,7 @@ export class DataflowControlService {
|
|||
console.log(`🚀 실행할 쿼리:`, deleteQuery);
|
||||
console.log(`📊 쿼리 파라미터:`, whereValues);
|
||||
|
||||
const result = await prisma.$executeRawUnsafe(
|
||||
deleteQuery,
|
||||
...whereValues
|
||||
);
|
||||
const result = await query(deleteQuery, whereValues);
|
||||
|
||||
console.log(`✅ DELETE 성공:`, {
|
||||
table: tableName,
|
||||
|
|
@ -1089,18 +1083,15 @@ export class DataflowControlService {
|
|||
columnName: string
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
const result = await prisma.$queryRawUnsafe<Array<{ exists: boolean }>>(
|
||||
`
|
||||
SELECT EXISTS (
|
||||
const result = await query<{ exists: boolean }>(
|
||||
`SELECT EXISTS (
|
||||
SELECT 1
|
||||
FROM information_schema.columns
|
||||
WHERE table_name = $1
|
||||
AND column_name = $2
|
||||
AND table_schema = 'public'
|
||||
) as exists
|
||||
`,
|
||||
tableName,
|
||||
columnName
|
||||
) as exists`,
|
||||
[tableName, columnName]
|
||||
);
|
||||
|
||||
return result[0]?.exists || false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue