From 4efec8d7585dd153466239c47d6ac079d8afcd33 Mon Sep 17 00:00:00 2001 From: leeheejin Date: Wed, 24 Sep 2025 10:30:36 +0900 Subject: [PATCH] =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=B2=A0=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=ED=8B=80=EB=A6=B0=20=EB=B9=84=EB=B0=80=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=9E=85=EB=A0=A5=EC=8B=9C=20=EC=97=B0=EA=B2=B0?= =?UTF-8?q?=EA=B1=B0=EB=B6=80=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend-node/prisma/schema.prisma | 16 + backend-node/src/app.ts | 2 + .../controllers/dbTypeCategoryController.ts | 215 ++++++++++++ .../src/routes/dbTypeCategoryRoutes.ts | 49 +++ .../src/routes/externalDbConnectionRoutes.ts | 42 +++ .../src/services/dbTypeCategoryService.ts | 320 ++++++++++++++++++ .../services/externalDbConnectionService.ts | 118 ++++++- 7 files changed, 760 insertions(+), 2 deletions(-) create mode 100644 backend-node/src/controllers/dbTypeCategoryController.ts create mode 100644 backend-node/src/routes/dbTypeCategoryRoutes.ts create mode 100644 backend-node/src/services/dbTypeCategoryService.ts diff --git a/backend-node/prisma/schema.prisma b/backend-node/prisma/schema.prisma index 2ba11203..d9dfa8ad 100644 --- a/backend-node/prisma/schema.prisma +++ b/backend-node/prisma/schema.prisma @@ -35,6 +35,20 @@ model external_call_configs { updated_date DateTime? @default(now()) @updatedAt @db.Timestamp(6) } +model db_type_categories { + type_code String @id @db.VarChar(20) + display_name String @db.VarChar(50) + icon String? @db.VarChar(50) + color String? @db.VarChar(20) + sort_order Int? @default(0) + is_active Boolean @default(true) + created_at DateTime @default(now()) @db.Timestamp(6) + updated_at DateTime @default(now()) @updatedAt @db.Timestamp(6) + + // 관계 설정 + external_db_connections external_db_connections[] +} + model external_db_connections { id Int @id @default(autoincrement()) connection_name String @db.VarChar(100) @@ -59,9 +73,11 @@ model external_db_connections { updated_by String? @db.VarChar(50) // 관계 + db_type_category db_type_categories? @relation(fields: [db_type], references: [type_code]) collection_configs data_collection_configs[] @@index([connection_name], map: "idx_external_db_connections_name") + @@index([db_type], map: "idx_external_db_connections_db_type") } model admin_supply_mng { diff --git a/backend-node/src/app.ts b/backend-node/src/app.ts index 9394d3d3..13d96767 100644 --- a/backend-node/src/app.ts +++ b/backend-node/src/app.ts @@ -31,6 +31,7 @@ import layoutRoutes from "./routes/layoutRoutes"; import dataRoutes from "./routes/dataRoutes"; import testButtonDataflowRoutes from "./routes/testButtonDataflowRoutes"; import externalDbConnectionRoutes from "./routes/externalDbConnectionRoutes"; +import dbTypeCategoryRoutes from "./routes/dbTypeCategoryRoutes"; import ddlRoutes from "./routes/ddlRoutes"; import entityReferenceRoutes from "./routes/entityReferenceRoutes"; // import collectionRoutes from "./routes/collectionRoutes"; // 임시 주석 @@ -129,6 +130,7 @@ app.use("/api/screen", screenStandardRoutes); app.use("/api/data", dataRoutes); app.use("/api/test-button-dataflow", testButtonDataflowRoutes); app.use("/api/external-db-connections", externalDbConnectionRoutes); +app.use("/api/db-type-categories", dbTypeCategoryRoutes); app.use("/api/ddl", ddlRoutes); app.use("/api/entity-reference", entityReferenceRoutes); // app.use("/api/collections", collectionRoutes); // 임시 주석 diff --git a/backend-node/src/controllers/dbTypeCategoryController.ts b/backend-node/src/controllers/dbTypeCategoryController.ts new file mode 100644 index 00000000..af54e405 --- /dev/null +++ b/backend-node/src/controllers/dbTypeCategoryController.ts @@ -0,0 +1,215 @@ +import { Request, Response } from "express"; +import { DbTypeCategoryService } from "../services/dbTypeCategoryService"; +import { AuthenticatedRequest } from "../types/auth"; + +export class DbTypeCategoryController { + /** + * GET /api/db-type-categories + * 모든 DB 타입 카테고리 조회 + */ + static async getAllCategories(req: AuthenticatedRequest, res: Response) { + try { + const result = await DbTypeCategoryService.getAllCategories(); + + if (result.success) { + return res.json(result); + } else { + return res.status(400).json(result); + } + } catch (error) { + console.error("DB 타입 카테고리 조회 오류:", error); + return res.status(500).json({ + success: false, + message: "DB 타입 카테고리 조회 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }); + } + } + + /** + * GET /api/db-type-categories/:typeCode + * 특정 DB 타입 카테고리 조회 + */ + static async getCategoryByTypeCode(req: AuthenticatedRequest, res: Response) { + try { + const { typeCode } = req.params; + + if (!typeCode) { + return res.status(400).json({ + success: false, + message: "DB 타입 코드가 필요합니다." + }); + } + + const result = await DbTypeCategoryService.getCategoryByTypeCode(typeCode); + + if (result.success) { + return res.json(result); + } else { + return res.status(404).json(result); + } + } catch (error) { + console.error("DB 타입 카테고리 조회 오류:", error); + return res.status(500).json({ + success: false, + message: "DB 타입 카테고리 조회 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }); + } + } + + /** + * POST /api/db-type-categories + * DB 타입 카테고리 생성 + */ + static async createCategory(req: AuthenticatedRequest, res: Response) { + try { + const { type_code, display_name, icon, color, sort_order } = req.body; + + if (!type_code || !display_name) { + return res.status(400).json({ + success: false, + message: "DB 타입 코드와 표시명은 필수입니다." + }); + } + + const result = await DbTypeCategoryService.createCategory({ + type_code, + display_name, + icon, + color, + sort_order + }); + + if (result.success) { + return res.status(201).json(result); + } else { + return res.status(400).json(result); + } + } catch (error) { + console.error("DB 타입 카테고리 생성 오류:", error); + return res.status(500).json({ + success: false, + message: "DB 타입 카테고리 생성 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }); + } + } + + /** + * PUT /api/db-type-categories/:typeCode + * DB 타입 카테고리 수정 + */ + static async updateCategory(req: AuthenticatedRequest, res: Response) { + try { + const { typeCode } = req.params; + const { display_name, icon, color, sort_order, is_active } = req.body; + + if (!typeCode) { + return res.status(400).json({ + success: false, + message: "DB 타입 코드가 필요합니다." + }); + } + + const result = await DbTypeCategoryService.updateCategory(typeCode, { + display_name, + icon, + color, + sort_order, + is_active + }); + + if (result.success) { + return res.json(result); + } else { + return res.status(400).json(result); + } + } catch (error) { + console.error("DB 타입 카테고리 수정 오류:", error); + return res.status(500).json({ + success: false, + message: "DB 타입 카테고리 수정 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }); + } + } + + /** + * DELETE /api/db-type-categories/:typeCode + * DB 타입 카테고리 삭제 (비활성화) + */ + static async deleteCategory(req: AuthenticatedRequest, res: Response) { + try { + const { typeCode } = req.params; + + if (!typeCode) { + return res.status(400).json({ + success: false, + message: "DB 타입 코드가 필요합니다." + }); + } + + const result = await DbTypeCategoryService.deleteCategory(typeCode); + + if (result.success) { + return res.json(result); + } else { + return res.status(400).json(result); + } + } catch (error) { + console.error("DB 타입 카테고리 삭제 오류:", error); + return res.status(500).json({ + success: false, + message: "DB 타입 카테고리 삭제 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }); + } + } + + /** + * GET /api/db-type-categories/stats/connections + * DB 타입별 연결 통계 조회 + */ + static async getConnectionStatsByType(req: AuthenticatedRequest, res: Response) { + try { + const result = await DbTypeCategoryService.getConnectionStatsByType(); + + if (result.success) { + return res.json(result); + } else { + return res.status(400).json(result); + } + } catch (error) { + console.error("DB 타입별 통계 조회 오류:", error); + return res.status(500).json({ + success: false, + message: "DB 타입별 통계 조회 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }); + } + } + + /** + * POST /api/db-type-categories/initialize + * 기본 DB 타입 카테고리 초기화 + */ + static async initializeDefaultCategories(req: AuthenticatedRequest, res: Response) { + try { + const result = await DbTypeCategoryService.initializeDefaultCategories(); + + if (result.success) { + return res.json(result); + } else { + return res.status(400).json(result); + } + } catch (error) { + console.error("기본 카테고리 초기화 오류:", error); + return res.status(500).json({ + success: false, + message: "기본 카테고리 초기화 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }); + } + } +} diff --git a/backend-node/src/routes/dbTypeCategoryRoutes.ts b/backend-node/src/routes/dbTypeCategoryRoutes.ts new file mode 100644 index 00000000..09c3763e --- /dev/null +++ b/backend-node/src/routes/dbTypeCategoryRoutes.ts @@ -0,0 +1,49 @@ +import { Router } from "express"; +import { DbTypeCategoryController } from "../controllers/dbTypeCategoryController"; +import { authenticateToken } from "../middleware/authMiddleware"; + +const router = Router(); + +/** + * GET /api/db-type-categories + * 모든 DB 타입 카테고리 조회 + */ +router.get("/", authenticateToken, DbTypeCategoryController.getAllCategories); + +/** + * GET /api/db-type-categories/stats/connections + * DB 타입별 연결 통계 조회 + */ +router.get("/stats/connections", authenticateToken, DbTypeCategoryController.getConnectionStatsByType); + +/** + * GET /api/db-type-categories/:typeCode + * 특정 DB 타입 카테고리 조회 + */ +router.get("/:typeCode", authenticateToken, DbTypeCategoryController.getCategoryByTypeCode); + +/** + * POST /api/db-type-categories + * DB 타입 카테고리 생성 + */ +router.post("/", authenticateToken, DbTypeCategoryController.createCategory); + +/** + * POST /api/db-type-categories/initialize + * 기본 DB 타입 카테고리 초기화 + */ +router.post("/initialize", authenticateToken, DbTypeCategoryController.initializeDefaultCategories); + +/** + * PUT /api/db-type-categories/:typeCode + * DB 타입 카테고리 수정 + */ +router.put("/:typeCode", authenticateToken, DbTypeCategoryController.updateCategory); + +/** + * DELETE /api/db-type-categories/:typeCode + * DB 타입 카테고리 삭제 (비활성화) + */ +router.delete("/:typeCode", authenticateToken, DbTypeCategoryController.deleteCategory); + +export default router; diff --git a/backend-node/src/routes/externalDbConnectionRoutes.ts b/backend-node/src/routes/externalDbConnectionRoutes.ts index b25f6fe6..344dc8d2 100644 --- a/backend-node/src/routes/externalDbConnectionRoutes.ts +++ b/backend-node/src/routes/externalDbConnectionRoutes.ts @@ -85,6 +85,46 @@ router.get( } ); +/** + * GET /api/external-db-connections/grouped + * DB 타입별로 그룹화된 외부 DB 연결 목록 조회 + */ +router.get( + "/grouped", + authenticateToken, + async (req: AuthenticatedRequest, res: Response) => { + try { + const filter: ExternalDbConnectionFilter = { + db_type: req.query.db_type as string, + is_active: req.query.is_active as string, + company_code: req.query.company_code as string, + search: req.query.search as string, + }; + + // 빈 값 제거 + Object.keys(filter).forEach((key) => { + if (!filter[key as keyof ExternalDbConnectionFilter]) { + delete filter[key as keyof ExternalDbConnectionFilter]; + } + }); + + const result = await ExternalDbConnectionService.getConnectionsGroupedByType(filter); + + if (result.success) { + return res.status(200).json(result); + } else { + return res.status(400).json(result); + } + } catch (error) { + console.error("그룹화된 외부 DB 연결 목록 조회 오류:", error); + return res.status(500).json({ + success: false, + message: "그룹화된 연결 목록 조회 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }); + } + } +); /** * GET /api/external-db-connections/:id @@ -264,6 +304,8 @@ router.post( // 테스트용 비밀번호가 제공된 경우 사용 const testData = req.body.password ? { password: req.body.password } : undefined; + console.log(`🔍 [API] 연결테스트 요청 - ID: ${id}, 비밀번호 제공됨: ${!!req.body.password}`); + const result = await ExternalDbConnectionService.testConnectionById(id, testData); return res.status(200).json({ diff --git a/backend-node/src/services/dbTypeCategoryService.ts b/backend-node/src/services/dbTypeCategoryService.ts new file mode 100644 index 00000000..1b00f328 --- /dev/null +++ b/backend-node/src/services/dbTypeCategoryService.ts @@ -0,0 +1,320 @@ +import { PrismaClient } from "@prisma/client"; + +const prisma = new PrismaClient(); + +export interface DbTypeCategory { + type_code: string; + display_name: string; + icon?: string | null; + color?: string | null; + sort_order?: number | null; + is_active: boolean; + created_at: Date; + updated_at: Date; +} + +export interface CreateDbTypeCategoryRequest { + type_code: string; + display_name: string; + icon?: string; + color?: string; + sort_order?: number; +} + +export interface UpdateDbTypeCategoryRequest { + display_name?: string; + icon?: string; + color?: string; + sort_order?: number; + is_active?: boolean; +} + +export interface ApiResponse { + success: boolean; + data?: T; + message: string; + error?: string; +} + +export class DbTypeCategoryService { + /** + * 모든 DB 타입 카테고리 조회 + */ + static async getAllCategories(): Promise> { + try { + const categories = await prisma.db_type_categories.findMany({ + where: { is_active: true }, + orderBy: [ + { sort_order: 'asc' }, + { display_name: 'asc' } + ] + }); + + return { + success: true, + data: categories, + message: "DB 타입 카테고리 목록을 조회했습니다." + }; + } catch (error) { + console.error("DB 타입 카테고리 조회 오류:", error); + return { + success: false, + message: "DB 타입 카테고리 조회 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }; + } + } + + /** + * 특정 DB 타입 카테고리 조회 + */ + static async getCategoryByTypeCode(typeCode: string): Promise> { + try { + const category = await prisma.db_type_categories.findUnique({ + where: { type_code: typeCode } + }); + + if (!category) { + return { + success: false, + message: "해당 DB 타입 카테고리를 찾을 수 없습니다." + }; + } + + return { + success: true, + data: category, + message: "DB 타입 카테고리를 조회했습니다." + }; + } catch (error) { + console.error("DB 타입 카테고리 조회 오류:", error); + return { + success: false, + message: "DB 타입 카테고리 조회 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }; + } + } + + /** + * DB 타입 카테고리 생성 + */ + static async createCategory(data: CreateDbTypeCategoryRequest): Promise> { + try { + // 중복 체크 + const existing = await prisma.db_type_categories.findUnique({ + where: { type_code: data.type_code } + }); + + if (existing) { + return { + success: false, + message: "이미 존재하는 DB 타입 코드입니다." + }; + } + + const category = await prisma.db_type_categories.create({ + data: { + type_code: data.type_code, + display_name: data.display_name, + icon: data.icon, + color: data.color, + sort_order: data.sort_order || 0 + } + }); + + return { + success: true, + data: category, + message: "DB 타입 카테고리가 생성되었습니다." + }; + } catch (error) { + console.error("DB 타입 카테고리 생성 오류:", error); + return { + success: false, + message: "DB 타입 카테고리 생성 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }; + } + } + + /** + * DB 타입 카테고리 수정 + */ + static async updateCategory(typeCode: string, data: UpdateDbTypeCategoryRequest): Promise> { + try { + const category = await prisma.db_type_categories.update({ + where: { type_code: typeCode }, + data: { + display_name: data.display_name, + icon: data.icon, + color: data.color, + sort_order: data.sort_order, + is_active: data.is_active, + updated_at: new Date() + } + }); + + return { + success: true, + data: category, + message: "DB 타입 카테고리가 수정되었습니다." + }; + } catch (error) { + console.error("DB 타입 카테고리 수정 오류:", error); + return { + success: false, + message: "DB 타입 카테고리 수정 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }; + } + } + + /** + * DB 타입 카테고리 삭제 (비활성화) + */ + static async deleteCategory(typeCode: string): Promise> { + try { + // 해당 타입을 사용하는 연결이 있는지 확인 + const connectionsCount = await prisma.external_db_connections.count({ + where: { + db_type: typeCode, + is_active: "Y" + } + }); + + if (connectionsCount > 0) { + return { + success: false, + message: `해당 DB 타입을 사용하는 연결이 ${connectionsCount}개 있어 삭제할 수 없습니다.` + }; + } + + await prisma.db_type_categories.update({ + where: { type_code: typeCode }, + data: { + is_active: false, + updated_at: new Date() + } + }); + + return { + success: true, + message: "DB 타입 카테고리가 삭제되었습니다." + }; + } catch (error) { + console.error("DB 타입 카테고리 삭제 오류:", error); + return { + success: false, + message: "DB 타입 카테고리 삭제 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }; + } + } + + /** + * DB 타입별 연결 통계 조회 + */ + static async getConnectionStatsByType(): Promise> { + try { + const stats = await prisma.external_db_connections.groupBy({ + by: ['db_type'], + where: { is_active: "Y" }, + _count: { + id: true + } + }); + + // 카테고리 정보와 함께 반환 + const categories = await prisma.db_type_categories.findMany({ + where: { is_active: true } + }); + + const result = categories.map(category => { + const stat = stats.find(s => s.db_type === category.type_code); + return { + ...category, + connection_count: stat?._count.id || 0 + }; + }); + + return { + success: true, + data: result, + message: "DB 타입별 연결 통계를 조회했습니다." + }; + } catch (error) { + console.error("DB 타입별 통계 조회 오류:", error); + return { + success: false, + message: "DB 타입별 통계 조회 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }; + } + } + + /** + * 기본 DB 타입 카테고리 초기화 + */ + static async initializeDefaultCategories(): Promise> { + try { + const defaultCategories = [ + { + type_code: 'postgresql', + display_name: 'PostgreSQL', + icon: 'postgresql', + color: '#336791', + sort_order: 1 + }, + { + type_code: 'oracle', + display_name: 'Oracle', + icon: 'oracle', + color: '#F80000', + sort_order: 2 + }, + { + type_code: 'mysql', + display_name: 'MySQL', + icon: 'mysql', + color: '#4479A1', + sort_order: 3 + }, + { + type_code: 'mariadb', + display_name: 'MariaDB', + icon: 'mariadb', + color: '#003545', + sort_order: 4 + }, + { + type_code: 'mssql', + display_name: 'SQL Server', + icon: 'mssql', + color: '#CC2927', + sort_order: 5 + } + ]; + + for (const category of defaultCategories) { + await prisma.db_type_categories.upsert({ + where: { type_code: category.type_code }, + update: {}, + create: category + }); + } + + return { + success: true, + message: "기본 DB 타입 카테고리가 초기화되었습니다." + }; + } catch (error) { + console.error("기본 카테고리 초기화 오류:", error); + return { + success: false, + message: "기본 카테고리 초기화 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }; + } + } +} diff --git a/backend-node/src/services/externalDbConnectionService.ts b/backend-node/src/services/externalDbConnectionService.ts index 9a54754e..486b7449 100644 --- a/backend-node/src/services/externalDbConnectionService.ts +++ b/backend-node/src/services/externalDbConnectionService.ts @@ -81,6 +81,93 @@ export class ExternalDbConnectionService { } } + /** + * DB 타입별로 그룹화된 외부 DB 연결 목록 조회 + */ + static async getConnectionsGroupedByType( + filter: ExternalDbConnectionFilter = {} + ): Promise>> { + try { + // 기본 연결 목록 조회 + const connectionsResult = await this.getConnections(filter); + + if (!connectionsResult.success || !connectionsResult.data) { + return { + success: false, + message: "연결 목록 조회에 실패했습니다." + }; + } + + // DB 타입 카테고리 정보 조회 + const categories = await prisma.db_type_categories.findMany({ + where: { is_active: true }, + orderBy: [ + { sort_order: 'asc' }, + { display_name: 'asc' } + ] + }); + + // DB 타입별로 그룹화 + const groupedConnections: Record = {}; + + // 카테고리 정보를 포함한 그룹 초기화 + categories.forEach((category: any) => { + groupedConnections[category.type_code] = { + category: { + type_code: category.type_code, + display_name: category.display_name, + icon: category.icon, + color: category.color, + sort_order: category.sort_order + }, + connections: [] + }; + }); + + // 연결을 해당 타입 그룹에 배치 + connectionsResult.data.forEach(connection => { + if (groupedConnections[connection.db_type]) { + groupedConnections[connection.db_type].connections.push(connection); + } else { + // 카테고리에 없는 DB 타입인 경우 기타 그룹에 추가 + if (!groupedConnections['other']) { + groupedConnections['other'] = { + category: { + type_code: 'other', + display_name: '기타', + icon: 'database', + color: '#6B7280', + sort_order: 999 + }, + connections: [] + }; + } + groupedConnections['other'].connections.push(connection); + } + }); + + // 연결이 없는 빈 그룹 제거 + Object.keys(groupedConnections).forEach(key => { + if (groupedConnections[key].connections.length === 0) { + delete groupedConnections[key]; + } + }); + + return { + success: true, + data: groupedConnections, + message: `DB 타입별로 그룹화된 연결 목록을 조회했습니다.` + }; + } catch (error) { + console.error("그룹화된 연결 목록 조회 실패:", error); + return { + success: false, + message: "그룹화된 연결 목록 조회 중 오류가 발생했습니다.", + error: error instanceof Error ? error.message : "알 수 없는 오류" + }; + } + } + /** * 특정 외부 DB 연결 조회 */ @@ -371,8 +458,10 @@ export class ExternalDbConnectionService { let password: string | null; if (testData?.password) { password = testData.password; + console.log(`🔍 [연결테스트] 새로 입력된 비밀번호 사용: ${password.substring(0, 3)}***`); } else { password = await this.getDecryptedPassword(id); + console.log(`🔍 [연결테스트] 저장된 비밀번호 사용: ${password ? password.substring(0, 3) + '***' : 'null'}`); } if (!password) { @@ -398,9 +487,34 @@ export class ExternalDbConnectionService { ssl: connection.ssl_enabled === "Y" ? { rejectUnauthorized: false } : false }; - // DatabaseConnectorFactory를 통한 연결 테스트 - const connector = await DatabaseConnectorFactory.createConnector(connection.db_type, config, id); + // 연결 테스트용 임시 커넥터 생성 (캐시 사용하지 않음) + let connector: any; + switch (connection.db_type.toLowerCase()) { + case 'postgresql': + const { PostgreSQLConnector } = await import('../database/PostgreSQLConnector'); + connector = new PostgreSQLConnector(config); + break; + case 'oracle': + const { OracleConnector } = await import('../database/OracleConnector'); + connector = new OracleConnector(config); + break; + case 'mariadb': + case 'mysql': + const { MariaDBConnector } = await import('../database/MariaDBConnector'); + connector = new MariaDBConnector(config); + break; + case 'mssql': + const { MSSQLConnector } = await import('../database/MSSQLConnector'); + connector = new MSSQLConnector(config); + break; + default: + throw new Error(`지원하지 않는 데이터베이스 타입: ${connection.db_type}`); + } + + console.log(`🔍 [연결테스트] 새 커넥터로 DB 연결 시도 - Host: ${config.host}, DB: ${config.database}, User: ${config.user}`); + const testResult = await connector.testConnection(); + console.log(`🔍 [연결테스트] 결과 - Success: ${testResult.success}, Message: ${testResult.message}`); return { success: testResult.success,