Node.js와 PostgreSQL: pg 연결 최적화와 풀링
Node.js 환경에서 PostgreSQL 연결을 안정적으로 구성하고 pg 모듈의 Pool 설정과 쿼리 성능을 개선하는 실제적 접근과 설정 예시를 제공. 연결 최적화 방법
목차
개요
Node.js 애플리케이션에서 PostgreSQL을 효율적으로 다루려면 단순한 연결 방식만으로는 한계가 생긴다. 여러 동시 요청, 느린 쿼리, 커넥션 누수 문제는 서비스 성능과 안정성에 직접 영향을 준다. 이 글은 Node.js PostgreSQL pg 연결 문제를 이해하고, pg 모듈의 Pool 설정 Node 환경에서 최적화하는 현실적 방법을 제시한다.
왜 풀링이 필요한가
연결 비용과 동시성
Postgres 연결은 생성 비용이 크다. 매 요청마다 새 연결을 만들면 지연과 자원 낭비가 발생한다. Pool을 사용하면 연결을 재사용하며 동시성을 제어할 수 있다. 특히 작은 인스턴스에서 많은 연결을 동시에 열면 데이터베이스에 과부하가 걸린다.
연결 누수 방지
풀은 연결을 추적하고 재사용 타이밍을 관리한다. 적절한 타임아웃과 오류 처리로 누수를 막을 수 있다.
기본 설정과 예시
우선 pg 설치와 간단한 Pool 생성 예시부터 보자. 이 예시는 기본적인 Pool 사용 패턴을 보여준다.
const { Pool } = require('pg')
const pool = new Pool({
user: 'dbuser',
host: 'localhost',
database: 'mydb',
password: 'secret',
port: 5432,
max: 20, // 최대 커넥션 수
idleTimeoutMillis: 30000, // 유휴 연결 타임아웃
connectionTimeoutMillis: 2000 // 연결 시도 타임아웃
})
module.exports = pool
핵심 설정 항목과 최적화 포인트
- max: 동시 연결 수를 제어한다. 애플리케이션 스레드와 DB 리소스를 고려해 설정한다.
- idleTimeoutMillis: 유휴 연결을 얼마나 오래 유지할지 결정한다. 너무 길면 불필요한 리소스 점유, 너무 짧으면 재연결 비용 발생.
- connectionTimeoutMillis: 연결 시도 최대 대기 시간. 느린 네트워크 환경에서 의미 있다.
- statement_timeout 및 query_timeout: 쿼리 단위 타임아웃으로 느린 쿼리를 차단한다.
- application_name: DB 측에서 연결을 구분할 때 유용하다.
설정 시 고려사항
인스턴스 크기와 동시 사용자 수를 기준으로 max를 정하되, 데이터베이스의 동시 연결 허용치보다 작게 설정한다. 풀 하나를 전역으로 두고 여러 곳에서 재사용하는 방식이 권장된다.
쿼리 패턴과 성능 개선
연결 풀만으로는 충분하지 않다. 쿼리 작성과 실행 패턴도 중요하다.
- 파라미터화된 쿼리 사용으로 계획 재사용 유도
- Prepared Statement 활용으로 반복 쿼리 최적화
- 배치 처리와 bulk insert로 네트워크 왕복 최소화
- 필요 없는 컬럼 조회 피하기(SELECT *)
- 트랜잭션은 필요한 범위에서만 사용
스트리밍과 대용량 결과 처리
대량 데이터 조회 시에는 모든 결과를 메모리에 적재하지 않고 스트리밍으로 처리한다. pg-query-stream 같은 도구를 사용하면 메모리 사용을 줄일 수 있다.
오류 처리와 종료 절차
풀을 사용할 때는 오류 발생 시 연결을 반환하도록 반드시 처리해야 한다. 서버 종료 시에는 pool.end()로 연결을 정상 종료한다.
process.on('SIGINT', async () => {
try {
await pool.end()
console.log('pool closed')
process.exit(0)
} catch (err) {
console.error('error closing pool', err)
process.exit(1)
}
})
쿼리 내부에서 오류가 발생하면 finally 블록에서 client.release()를 호출해 연결을 반환한다. 이렇게 하면 커넥션 누수를 예방할 수 있다.
모니터링과 지표
운영 환경에서는 다음 지표를 모니터링한다.
- 활성 연결 수와 유휴 연결 수
- 쿼리 응답 시간 분포(P95, P99)
- 데드락 및 트랜잭션 대기 시간
- 연결 타임아웃 발생 빈도
이 지표를 통해 max 값을 조정하거나 쿼리 최적화 우선순위를 정할 수 있다.
결론
Node.js PostgreSQL pg 연결 환경에서는 Pool 설정 Node와 쿼리 패턴 개선이 성능과 안정성의 핵심이다. 적절한 max, 타임아웃 설정, 쿼리 최적화, 오류 처리, 모니터링을 조합하면 확장성과 신뢰성을 크게 향상시킬 수 있다. 작은 설정 변경으로도 응답성 개선과 리소스 절감 효과를 기대할 수 있다.