PostgreSQL 53300 오류 원인과 해결 방법 완벽 가이드

53300
2026년 07월 16일 | DBMS Error 가이드

이 글에서 다루는 내용

53300 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.

53300 too many connections 는?

PostgreSQL 에러 코드 53300, too many connections는 데이터베이스 서버에 허용된 최대 동시 접속 수를 초과했을 때 발생하는 에러입니다. PostgreSQL은 postgresql.confmax_connections 파라미터로 최대 연결 수를 제한하며, 이 한도를 넘는 순간 새로운 클라이언트 연결 요청은 즉시 거부됩니다. 특히 트래픽이 급격히 증가하거나 애플리케이션에서 커넥션 풀을 제대로 관리하지 않을 경우 운영 환경에서 매우 빈번하게 발생하는 치명적인 에러입니다.


주요 발생 원인

1. 커넥션 풀(Connection Pool) 미사용 또는 잘못된 설정

가장 흔한 원인으로, 애플리케이션이 데이터베이스와 통신할 때마다 새로운 커넥션을 생성하고 제대로 반환하지 않는 경우입니다. 특히 Spring Boot, Django, Node.js 등의 프레임워크에서 커넥션 풀 설정 없이 직접 연결을 사용하거나, 풀의 최대 크기(pool_size)가 서버의 max_connections를 고려하지 않고 설정된 경우 순식간에 연결이 고갈됩니다. 예를 들어 마이크로서비스가 10개 있고 각 서비스 인스턴스가 100개의 커넥션 풀을 가진다면 단순 계산만으로도 1,000개의 연결이 필요하게 됩니다.

2. 유휴 연결(Idle Connection) 누적

애플리케이션이 커넥션을 사용한 후 명시적으로 닫지 않거나, 커넥션 풀에 반환하지 않아 idle 또는 idle in transaction 상태의 연결이 계속 누적되는 경우입니다. idle in transaction 상태는 특히 위험한데, 트랜잭션을 시작(BEGIN)한 후 커밋이나 롤백 없이 방치된 커넥션으로, 락(Lock)까지 점유하여 이중으로 문제를 일으킵니다. 장시간 운영된 시스템에서 이러한 좀비 커넥션이 쌓이다가 피크 타임에 한꺼번에 임계치를 초과하는 패턴이 매우 자주 관찰됩니다.

3. max_connections 설정값이 너무 낮거나 서버 사양 대비 부적절한 경우

PostgreSQL의 기본 max_connections 값은 100으로, 소규모 개발 환경에는 적합하지만 프로덕션 환경에서는 턱없이 부족할 수 있습니다. 반대로 무조건 높게 설정한다고 해결되는 것이 아니며, 각 커넥션은 약 5~10MB의 메모리를 소비하므로 서버의 RAM 용량을 초과하면 OOM(Out of Memory) 문제로 이어집니다. 서버 사양, 워크로드 특성, 실제 동시 사용자 수를 종합적으로 고려한 적절한 값 설정이 반드시 필요합니다.


해결 방법

현재 연결 상태 즉시 확인

가장 먼저 현재 연결 현황을 파악해야 합니다.

-- 전체 연결 수 및 상태별 요약
SELECT 
    state,
    count(*) AS connection_count,
    max(now() - state_change) AS max_duration
FROM pg_stat_activity
WHERE pid <> pg_backend_pid()
GROUP BY state
ORDER BY connection_count DESC;

-- max_connections 대비 현재 사용률 확인
SELECT 
    max_conn,
    used_conn,
    reserved_conn,
    max_conn - used_conn - reserved_conn AS available_conn
FROM 
    (SELECT setting::int AS max_conn FROM pg_settings WHERE name = 'max_connections') mc,
    (SELECT count(*) AS used_conn FROM pg_stat_activity) ua,
    (SELECT setting::int AS reserved_conn FROM pg_settings WHERE name = 'superuser_reserved_connections') rc;

유휴 및 장기 실행 연결 강제 종료

긴급 상황에서는 문제가 되는 연결을 강제로 종료할 수 있습니다.

-- 10분 이상 idle 상태인 연결 종료
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE state = 'idle'
  AND state_change < now() - interval '10 minutes'
  AND pid <> pg_backend_pid();

-- 5분 이상 idle in transaction 상태인 위험한 연결 종료
SELECT pg_terminate_backend(pid), query, usename, application_name
FROM pg_stat_activity
WHERE state = 'idle in transaction'
  AND state_change < now() - interval '5 minutes'
  AND pid <> pg_backend_pid();

max_connections 및 관련 파라미터 조정

-- 현재 설정값 확인
SHOW max_connections;
SHOW superuser_reserved_connections;

-- postgresql.conf 변경 후 재시작 없이 확인 가능한 설정들
-- max_connections 는 재시작 필요 (context: postmaster)
SELECT name, setting, unit, context
FROM pg_settings
WHERE name IN (
    'max_connections',
    'superuser_reserved_connections',
    'idle_in_transaction_session_timeout',
    'statement_timeout'
);

postgresql.conf에서 직접 수정:

-- postgresql.conf 예시 설정
-- max_connections = 200          # 기본값 100에서 상향 (재시작 필요)
-- idle_in_transaction_session_timeout = '5min'  # idle in transaction 자동 종료
-- tcp_keepalives_idle = 60       # TCP 레벨 좀비 연결 감지

idle_in_transaction_session_timeout 설정으로 자동 정리

-- 세션 레벨에서 즉시 적용 (테스트용)
SET idle_in_transaction_session_timeout = '5min';

-- 특정 롤(Role)에 영구 적용
ALTER ROLE app_user SET idle_in_transaction_session_timeout = '300000'; -- 5분 (ms 단위)

-- 데이터베이스 레벨에 적용
ALTER DATABASE mydb SET idle_in_transaction_session_timeout = '300000';

PgBouncer를 활용한 커넥션 풀링 (권장)

PgBouncer 설정 예시(pgbouncer.ini):

-- PgBouncer 적용 후 연결 상태 확인 (PgBouncer admin console)
-- SHOW POOLS;
-- SHOW CLIENTS;
-- SHOW SERVERS;

-- PostgreSQL에서 PgBouncer를 통한 연결 확인
SELECT application_name, count(*)
FROM pg_stat_activity
WHERE application_name LIKE '%pgbouncer%'
GROUP BY application_name;

예방 방법

1. PgBouncer 등 커넥션 풀러 필수 도입 및 모니터링 자동화

프로덕션 환경에서는 애플리케이션과 PostgreSQL 사이에 반드시 PgBouncer와 같은 커넥션 풀러를 배치해야 합니다. PgBouncer의 transaction 모드를 사용하면 수천 개의 애플리케이션 연결을 수십 개의 실제 DB 연결로 다중화할 수 있어 극적인 효율 향상이 가능합니다. 아울러 Prometheus + Grafana, Datadog, pgBadger 등의 모니터링 도구를 활용해 pg_stat_activity 기반 연결 수 알림을 max_connections의 70~80% 수준에서 설정하여 사전에 경보를 받을 수 있도록 구성하는 것이 Best Practice입니다.

-- 모니터링용 뷰 생성 (재사용 가능)
CREATE OR REPLACE VIEW v_connection_stats AS
SELECT
    datname AS database,
    usename AS username,
    application_name,
    state,
    count(*) AS connections,
    max(now() - state_change) AS longest_idle
FROM pg_stat_activity
WHERE pid <> pg_backend_pid()
GROUP BY datname, usename, application_name, state
ORDER BY connections DESC;

2. idle_in_transaction_session_timeout 및 statement_timeout 전역 설정

모든 프로덕션 PostgreSQL 인스턴스에는 idle_in_transaction_session_timeoutstatement_timeout을 반드시 설정해야 합니다. 이 두 파라미터는 좀비 연결과 장기 실행 쿼리로 인한 연결 고갈을 자동으로 방지하는 1차 방어선입니다. 일반적으로 idle_in_transaction_session_timeout은 5분, statement_timeout은 워크로드에 따라 30초~10분 사이로 설정하는 것이 권장됩니다.

-- postgresql.conf 권장 설정 (전역 적용)
-- idle_in_transaction_session_timeout = '5min'
-- statement_timeout = '30s'      # OLTP 환경 권장
-- lock_timeout = '10s'           # 락 대기 타임아웃

-- 설정 적용 확인
SELECT name, setting, unit
FROM pg_settings
WHERE name IN (
    'idle_in_transaction_session_timeout',
    'statement_timeout',
    'lock_timeout'
);

관련 에러

  • 53200 out_of_memory: max_connections를 과도하게 높여 각 연결의 메모리 합산이 서버 RAM을 초과할 때 함께 발생하는 에러입니다.
  • 55P03 lock_not_available: 연결이 폭증하면 락 경쟁도 심화되어 함께 나타나는 경우가 많습니다.
  • 57014 query_canceled: statement_timeout 설정으로 장기 실행 쿼리를 자동 종료할 때 발생하며, 53300 예방 설정과 연계됩니다.
  • 08006 connection_failure: 클라이언트 측에서 53300으로 인해 연결이 거부될 때 드라이버에 따라 이 에러 코드로 표시되기도 합니다.
DBMS 에러 코드 시리즈

주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.

본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.

댓글 남기기