Merge branch 'main' into feature/prisma-to-raw-query-phase1-complete
This commit is contained in:
127
backend-node/src/database/PostgreSQLService.ts
Normal file
127
backend-node/src/database/PostgreSQLService.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
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();
|
||||
});
|
||||
Reference in New Issue
Block a user