/** * 디지털 트윈 외부 DB (DO_DY) 연결 및 쿼리 테스트 스크립트 * READ-ONLY: SELECT 쿼리만 실행 */ import { Pool } from "pg"; import mysql from "mysql2/promise"; import { CredentialEncryption } from "../src/utils/credentialEncryption"; async function testDigitalTwinDb() { // 내부 DB 연결 (연결 정보 저장용) const internalPool = new Pool({ host: process.env.DB_HOST || "localhost", port: parseInt(process.env.DB_PORT || "5432"), database: process.env.DB_NAME || "plm", user: process.env.DB_USER || "postgres", password: process.env.DB_PASSWORD || "ph0909!!", }); const encryptionKey = process.env.ENCRYPTION_SECRET_KEY || "default-secret-key-for-development"; const encryption = new CredentialEncryption(encryptionKey); try { console.log("🚀 디지털 트윈 외부 DB 연결 테스트 시작\n"); // 디지털 트윈 외부 DB 연결 정보 const digitalTwinConnection = { name: "디지털트윈_DO_DY", description: "디지털 트윈 후판(자재) 재고 정보 데이터베이스 (MariaDB)", dbType: "mysql", // MariaDB는 MySQL 프로토콜 사용 host: "1.240.13.83", port: 4307, databaseName: "DO_DY", username: "root", password: "pohangms619!#", sslEnabled: false, isActive: true, }; console.log("📝 연결 정보:"); console.log(` - 이름: ${digitalTwinConnection.name}`); console.log(` - DB 타입: ${digitalTwinConnection.dbType}`); console.log(` - 호스트: ${digitalTwinConnection.host}:${digitalTwinConnection.port}`); console.log(` - 데이터베이스: ${digitalTwinConnection.databaseName}\n`); // 1. 외부 DB 직접 연결 테스트 console.log("🔍 외부 DB 직접 연결 테스트 중..."); const externalConnection = await mysql.createConnection({ host: digitalTwinConnection.host, port: digitalTwinConnection.port, database: digitalTwinConnection.databaseName, user: digitalTwinConnection.username, password: digitalTwinConnection.password, connectTimeout: 10000, }); console.log("✅ 외부 DB 연결 성공!\n"); // 2. SELECT 쿼리 실행 console.log("📊 WSTKKY 테이블 쿼리 실행 중...\n"); const query = ` SELECT SKUMKEY -- 제품번호 , SKUDESC -- 자재명 , SKUTHIC -- 두께 , SKUWIDT -- 폭 , SKULENG -- 길이 , SKUWEIG -- 중량 , STOTQTY -- 수량 , SUOMKEY -- 단위 FROM DO_DY.WSTKKY LIMIT 10 `; const [rows] = await externalConnection.execute(query); console.log("✅ 쿼리 실행 성공!\n"); console.log(`📦 조회된 데이터: ${Array.isArray(rows) ? rows.length : 0}건\n`); if (Array.isArray(rows) && rows.length > 0) { console.log("🔍 샘플 데이터 (첫 3건):\n"); rows.slice(0, 3).forEach((row: any, index: number) => { console.log(`[${index + 1}]`); console.log(` 제품번호(SKUMKEY): ${row.SKUMKEY}`); console.log(` 자재명(SKUDESC): ${row.SKUDESC}`); console.log(` 두께(SKUTHIC): ${row.SKUTHIC}`); console.log(` 폭(SKUWIDT): ${row.SKUWIDT}`); console.log(` 길이(SKULENG): ${row.SKULENG}`); console.log(` 중량(SKUWEIG): ${row.SKUWEIG}`); console.log(` 수량(STOTQTY): ${row.STOTQTY}`); console.log(` 단위(SUOMKEY): ${row.SUOMKEY}\n`); }); // 전체 데이터 JSON 출력 console.log("📄 전체 데이터 (JSON):"); console.log(JSON.stringify(rows, null, 2)); console.log("\n"); } await externalConnection.end(); // 3. 내부 DB에 연결 정보 저장 console.log("💾 내부 DB에 연결 정보 저장 중..."); const encryptedPassword = encryption.encrypt(digitalTwinConnection.password); // 중복 체크 const existingResult = await internalPool.query( "SELECT id FROM flow_external_db_connection WHERE name = $1", [digitalTwinConnection.name] ); let connectionId: number; if (existingResult.rows.length > 0) { connectionId = existingResult.rows[0].id; console.log(`⚠️ 이미 존재하는 연결 (ID: ${connectionId})`); // 기존 연결 업데이트 await internalPool.query( `UPDATE flow_external_db_connection SET description = $1, db_type = $2, host = $3, port = $4, database_name = $5, username = $6, password_encrypted = $7, ssl_enabled = $8, is_active = $9, updated_at = NOW(), updated_by = 'system' WHERE name = $10`, [ digitalTwinConnection.description, digitalTwinConnection.dbType, digitalTwinConnection.host, digitalTwinConnection.port, digitalTwinConnection.databaseName, digitalTwinConnection.username, encryptedPassword, digitalTwinConnection.sslEnabled, digitalTwinConnection.isActive, digitalTwinConnection.name, ] ); console.log(`✅ 연결 정보 업데이트 완료`); } else { // 새 연결 추가 const result = await internalPool.query( `INSERT INTO flow_external_db_connection ( name, description, db_type, host, port, database_name, username, password_encrypted, ssl_enabled, is_active, created_by ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, 'system') RETURNING id`, [ digitalTwinConnection.name, digitalTwinConnection.description, digitalTwinConnection.dbType, digitalTwinConnection.host, digitalTwinConnection.port, digitalTwinConnection.databaseName, digitalTwinConnection.username, encryptedPassword, digitalTwinConnection.sslEnabled, digitalTwinConnection.isActive, ] ); connectionId = result.rows[0].id; console.log(`✅ 새 연결 추가 완료 (ID: ${connectionId})`); } console.log("\n✅ 모든 테스트 완료!"); console.log(`\n📌 연결 ID: ${connectionId}`); console.log(" 이 ID를 사용하여 플로우 관리나 제어 관리에서 외부 DB를 연동할 수 있습니다."); } catch (error: any) { console.error("\n❌ 오류 발생:", error.message); console.error("상세 정보:", error); throw error; } finally { await internalPool.end(); } } // 스크립트 실행 testDigitalTwinDb() .then(() => { console.log("\n🎉 스크립트 완료"); process.exit(0); }) .catch((error) => { console.error("\n💥 스크립트 실패:", error); process.exit(1); });