ERP-node/backend-node/src/database/PostgreSQLService.ts

128 lines
2.9 KiB
TypeScript

import { Pool, PoolClient, QueryResult } from 'pg';
import config from '../config/environment';
/**
* PostgreSQL Raw Query 서비스
* Prisma 대신 직접 pg 라이브러리를 사용
*/
export class PostgreSQLService {
private static pool: Pool;
/**
* 데이터베이스 연결 풀 초기화
*/
static initialize() {
if (!this.pool) {
this.pool = new Pool({
connectionString: config.databaseUrl,
max: 20, // 최대 연결 수
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
// 연결 풀 이벤트 리스너
this.pool.on('connect', () => {
console.log('🔗 PostgreSQL 연결 성공');
});
this.pool.on('error', (err) => {
console.error('❌ PostgreSQL 연결 오류:', err);
});
}
}
/**
* 연결 풀 가져오기
*/
static getPool(): Pool {
if (!this.pool) {
this.initialize();
}
return this.pool;
}
/**
* 단일 쿼리 실행
*/
static async query(text: string, params?: any[]): Promise<QueryResult> {
const pool = this.getPool();
const start = Date.now();
try {
const result = await pool.query(text, params);
const duration = Date.now() - start;
if (config.debug) {
console.log('🔍 Query executed:', { text, duration: `${duration}ms`, rows: result.rowCount });
}
return result;
} catch (error) {
console.error('❌ Query error:', { text, params, error });
throw error;
}
}
/**
* 트랜잭션 실행
*/
static async transaction<T>(callback: (client: PoolClient) => Promise<T>): Promise<T> {
const pool = this.getPool();
const client = await pool.connect();
try {
await client.query('BEGIN');
const result = await callback(client);
await client.query('COMMIT');
return result;
} catch (error) {
await client.query('ROLLBACK');
throw error;
} finally {
client.release();
}
}
/**
* 연결 테스트
*/
static async testConnection(): Promise<boolean> {
try {
const result = await this.query('SELECT NOW() as current_time');
console.log('✅ PostgreSQL 연결 테스트 성공:', result.rows[0]);
return true;
} catch (error) {
console.error('❌ PostgreSQL 연결 테스트 실패:', error);
return false;
}
}
/**
* 연결 풀 종료
*/
static async close(): Promise<void> {
if (this.pool) {
await this.pool.end();
console.log('🔒 PostgreSQL 연결 풀 종료');
}
}
}
// 애플리케이션 시작 시 초기화
PostgreSQLService.initialize();
// 프로세스 종료 시 연결 정리
process.on('SIGINT', async () => {
await PostgreSQLService.close();
process.exit(0);
});
process.on('SIGTERM', async () => {
await PostgreSQLService.close();
process.exit(0);
});
process.on('beforeExit', async () => {
await PostgreSQLService.close();
});