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

57P03
2026년 09월 22일 | DBMS Error 가이드

이 글에서 다루는 내용

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

57P03 cannot connect now 는?

PostgreSQL 에러 코드 57P03 (cannot connect now)는 데이터베이스 서버가 현재 클라이언트의 새로운 연결 요청을 받아들일 수 없는 상태일 때 발생합니다. 주로 서버가 시작 중(startup), 종료 중(shutdown), 또는 복구 중(recovery)인 상태에서 클라이언트가 접속을 시도할 때 나타납니다. 이 에러는 서버 자체의 문제라기보다는 서버의 현재 상태(state) 에 의해 일시적으로 연결이 거부되는 상황을 의미하므로, 원인을 정확히 파악하고 대응하는 것이 중요합니다.


주요 발생 원인

1. PostgreSQL 서버 시작 또는 재시작 중 연결 시도

가장 흔한 원인은 서버가 아직 완전히 기동되지 않은 상태에서 클라이언트나 애플리케이션이 즉시 연결을 시도하는 경우입니다. PostgreSQL은 내부 초기화, 공유 메모리 설정, WAL(Write-Ahead Log) 복구 등의 과정을 모두 완료한 이후에야 비로소 새 연결을 허용하기 때문에, 서버 기동 직후 수 초~수십 초 사이에 이 에러가 빈번하게 발생합니다. 특히 대규모 데이터베이스 환경에서는 WAL 복구 시간이 길어져 이 에러가 더 오랫동안 지속될 수 있습니다.

2. Hot Standby 또는 Standby 서버의 복구(Recovery) 진행 중

PostgreSQL의 스트리밍 복제(Streaming Replication) 환경에서 Standby 서버가 아직 복구 모드(recovery mode)를 완전히 진입하지 못하거나, hot_standby = on 설정에도 불구하고 초기 복구 단계에 있을 때 이 에러가 발생합니다. Standby 서버는 WAL을 적용하면서 점진적으로 읽기 연결을 허용하는 상태로 전환되는데, 그 전환이 완료되기 전에 연결을 시도하면 57P03이 반환됩니다. 이 상황은 장애 조치(failover) 직후나 Standby 서버를 새로 구성할 때 특히 자주 목격됩니다.

3. pg_ctl stop / fast shutdown 또는 Smart Shutdown 진행 중

관리자가 pg_ctl stop 명령 또는 SIGTERM 시그널로 서버 종료를 시작한 이후, 서버가 완전히 종료되기 전까지의 짧은 시간 동안에도 새 연결 시도는 57P03 에러를 유발합니다. Smart Shutdown 모드에서는 기존 세션이 모두 종료될 때까지 기다리므로 이 상태가 상당히 오래 지속될 수 있습니다. 자동화된 배포 파이프라인이나 헬스체크 스크립트가 이 시점을 정확히 감지하지 못하면 연쇄적인 에러를 유발하기도 합니다.


해결 방법

원인 1 해결: 서버 상태 확인 후 재시도 로직 구현

서버 기동 중 발생하는 경우, 서버가 완전히 준비될 때까지 주기적으로 연결을 재시도하는 스크립트를 사용하는 것이 실무에서 가장 효과적입니다.

-- 서버가 준비 상태인지 확인하는 간단한 쿼리
-- pg_isready 명령어와 함께 사용 가능
SELECT pg_is_in_recovery();
-- 결과가 false이면 Primary로 정상 운영 중
-- 결과가 true이면 Standby/Recovery 상태

-- 서버 시작 시간 확인 (서버가 언제 기동됐는지 파악)
SELECT pg_postmaster_start_time();

쉘 스크립트 레벨에서 pg_isready를 활용한 재시도 루프:

-- psql 접속 전 상태 확인용 (PostgreSQL 내부에서 실행)
-- 현재 서버의 pid 및 상태 확인
SELECT pid, state, wait_event_type, wait_event
FROM pg_stat_activity
WHERE backend_type = 'autovacuum launcher'
   OR backend_type = 'background writer';

원인 2 해결: Hot Standby 설정 및 복구 상태 점검

Standby 서버의 복구 진행 상태를 모니터링하고, 복구가 충분히 진행된 이후에 연결을 허용하도록 설정합니다.

-- Standby 서버에서 복구 진행 상태 확인
SELECT
    now() AS current_time,
    pg_last_wal_receive_lsn() AS last_received_lsn,
    pg_last_wal_replay_lsn()  AS last_replayed_lsn,
    pg_is_in_recovery()       AS in_recovery,
    pg_last_xact_replay_timestamp() AS last_replay_time;

-- Primary와 Standby 간의 복제 지연(lag) 확인 (Primary에서 실행)
SELECT
    client_addr,
    state,
    sent_lsn,
    write_lsn,
    flush_lsn,
    replay_lsn,
    write_lag,
    flush_lag,
    replay_lag
FROM pg_stat_replication;

postgresql.conf에서 Hot Standby 관련 설정 확인:

-- 현재 hot_standby 설정 확인
SHOW hot_standby;

-- recovery_min_apply_delay 확인 (의도적 지연이 설정되어 있을 수 있음)
SHOW recovery_min_apply_delay;

원인 3 해결: 종료 모드 확인 및 graceful shutdown 관리

서버 종료 중 발생하는 경우, 현재 활성 연결과 세션을 먼저 확인하고 안전하게 종료합니다.

-- 현재 활성 연결 수 확인
SELECT
    count(*) AS total_connections,
    state,
    wait_event_type
FROM pg_stat_activity
WHERE pid <> pg_backend_pid()
GROUP BY state, wait_event_type
ORDER BY total_connections DESC;

-- 특정 데이터베이스로의 신규 연결 차단 (종료 준비 시 사용)
UPDATE pg_database
SET datallowconn = false
WHERE datname = 'your_database_name';

-- 해당 데이터베이스의 기존 연결 강제 종료
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'your_database_name'
  AND pid <> pg_backend_pid();

-- 작업 완료 후 다시 연결 허용
UPDATE pg_database
SET datallowconn = true
WHERE datname = 'your_database_name';

예방 방법

1. 애플리케이션 레벨에서 재시도(Retry) 로직과 Connection Pooling 구현

실무에서 가장 효과적인 예방책은 애플리케이션이 57P03 에러를 일시적인 에러(transient error)로 인식하고 지수 백오프(exponential backoff) 방식으로 재시도하도록 설계하는 것입니다. 또한 PgBouncer나 pgpool-II 같은 Connection Pooler를 앞단에 배치하면, 서버가 일시적으로 연결을 받지 못하는 상황에서도 클라이언트 연결을 큐잉(queuing)하거나 에러를 완충(buffering)할 수 있어 사용자에게 노출되는 에러를 크게 줄일 수 있습니다.

-- pg_hba.conf와 연계하여 특정 시간대 연결 모니터링
-- 연결 실패 이력 확인 (로그 기반)
SELECT
    log_time,
    error_severity,
    message
FROM pg_log  -- 실제 환경에서는 file_fdw 또는 외부 로그 파싱 필요
WHERE message LIKE '%cannot connect now%'
ORDER BY log_time DESC
LIMIT 20;

2. 서버 기동/종료 절차 표준화 및 헬스체크 스크립트 도입

배포 파이프라인이나 HA(High Availability) 솔루션에서 PostgreSQL 서버의 Ready 상태를 정확히 감지하는 헬스체크를 반드시 구현해야 합니다. pg_isready 유틸리티를 활용하거나, 아래와 같이 서버 내부 뷰를 조회하는 방식으로 서버가 완전히 준비되었는지 검증한 이후에 트래픽을 전환하는 절차를 표준화하세요.

-- 서버 준비 상태 종합 점검 쿼리
SELECT
    current_database()                          AS database,
    pg_postmaster_start_time()                  AS server_start_time,
    pg_is_in_recovery()                         AS is_standby,
    (SELECT count(*) FROM pg_stat_activity)     AS active_connections,
    (SELECT setting::int FROM pg_settings
     WHERE name = 'max_connections')            AS max_connections,
    now() - pg_postmaster_start_time()          AS uptime;

관련 에러

  • 57P01 (admin_shutdown): 관리자가 명시적으로 서버를 종료할 때 기존 연결에 반환되는 에러로, 57P03과 함께 shutdown 시나리오에서 자주 등장합니다.
  • 57P02 (crash_shutdown): 서버가 비정상적으로 크래시되어 종료된 경우 발생하며, 이후 서버 재기동 중 57P03이 뒤따라 나타날 수 있습니다.
  • 08006 (connection_failure): 네트워크 레벨의 연결 실패로, 57P03과 증상이 유사하지만 원인이 서버 상태가 아닌 네트워크/인프라 문제입니다.
  • 08001 (sqlclient_unable_to_establish_sqlconnection): 클라이언트가 서버에 연결 자체를 맺지 못한 경우로, 57P03보다 더 이른 단계에서 발생합니다.

DBMS 에러 코드 시리즈

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

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

댓글 남기기