2026년 06월 26일 | DBMS Error 가이드
이 글에서 다루는 내용
28P01 에러의 원인 분석, 해결 SQL, 예방 방법을 실무 관점에서 정리합니다.
28P01 invalid password 는?
PostgreSQL 에러 코드 28P01은 데이터베이스 접속 시 입력한 비밀번호가 올바르지 않을 때 발생하는 인증 실패 에러입니다. 이 에러는 클라이언트가 서버에 접속을 시도할 때 인증 단계(Authentication Phase)에서 발생하며, 서버는 접속을 즉시 거부합니다. 주로 psql, pg_dump, 애플리케이션 커넥션 풀, 또는 각종 ORM 라이브러리에서 자주 마주치는 에러로, 운영 환경에서 갑작스러운 서비스 장애로 이어질 수 있어 빠른 대응이 필요합니다.
주요 발생 원인
- 비밀번호 자체가 틀렸거나 최근에 변경된 경우
가장 흔한 원인으로, 데이터베이스 사용자의 비밀번호가 변경되었음에도 애플리케이션 설정 파일(예: .env, application.yml, database.ini)이나 커넥션 풀 설정에 이전 비밀번호가 그대로 남아있는 경우입니다. 특히 보안 정책에 따라 주기적으로 비밀번호를 교체하는 환경에서 자주 발생하며, 여러 서비스가 동일한 DB 계정을 공유할 때 일부 서비스만 업데이트되지 않아 에러가 산발적으로 발생하기도 합니다.
- pg_hba.conf 인증 방식 불일치
PostgreSQL의 클라이언트 인증 설정 파일인 pg_hba.conf에서 특정 사용자 또는 호스트에 대해 md5, scram-sha-256, password 등 다양한 인증 방식을 지정할 수 있습니다. 클라이언트가 서버가 요구하는 인증 방식과 다른 방식으로 접속을 시도하거나, 서버에 저장된 비밀번호 해시 형식이 pg_hba.conf에 설정된 인증 방식과 맞지 않을 경우에도 28P01 에러가 발생할 수 있습니다. 예를 들어, PostgreSQL 14 이후 기본 인증 방식이 scram-sha-256으로 변경되면서, 구버전 클라이언트 드라이버가 이를 지원하지 못해 발생하는 사례가 증가하고 있습니다.
- 역할(Role)이 존재하지 않거나 로그인 권한이 없는 경우
지정한 사용자 이름(Role)이 PostgreSQL에 아예 존재하지 않거나, 존재하더라도 LOGIN 권한이 부여되지 않은 경우입니다. 보안상의 이유로 PostgreSQL은 사용자가 존재하지 않는 경우와 비밀번호가 틀린 경우를 구분하지 않고 동일하게 28P01 에러를 반환하는데, 이는 사용자 존재 여부를 외부에 노출하지 않기 위한 의도적인 설계입니다. 따라서 에러 메시지만으로는 원인을 정확히 파악하기 어려우므로 서버 로그를 반드시 함께 확인해야 합니다.
해결 방법
원인 1: 비밀번호 재설정
슈퍼유저 또는 해당 권한이 있는 계정으로 접속하여 비밀번호를 재설정합니다.
-- 비밀번호 변경 (ALTER USER 또는 ALTER ROLE 모두 사용 가능)
ALTER USER myapp_user WITH PASSWORD 'NewSecurePassword!2024';
-- 또는 동일한 구문
ALTER ROLE myapp_user WITH PASSWORD 'NewSecurePassword!2024';
-- 변경 후 현재 사용자의 비밀번호 유효기간 확인
SELECT rolname, rolvaliduntil
FROM pg_roles
WHERE rolname = 'myapp_user';
비밀번호를 변경한 후에는 반드시 애플리케이션의 환경 변수나 설정 파일도 동기화해야 합니다.
-- 비밀번호 만료 기한 설정 (보안 정책 적용)
ALTER ROLE myapp_user WITH PASSWORD 'NewSecurePassword!2024'
VALID UNTIL '2025-12-31';
-- 만료 기한 제거 (무기한)
ALTER ROLE myapp_user WITH PASSWORD 'NewSecurePassword!2024'
VALID UNTIL 'infinity';
원인 2: pg_hba.conf 인증 방식 확인 및 조정
-- 현재 서버의 인증 관련 파라미터 확인
SHOW password_encryption;
-- pg_hba.conf 파일 위치 확인
SHOW hba_file;
-- pg_hba_file_rules 뷰로 현재 설정 확인 (PostgreSQL 10+)
SELECT line_number, type, database, user_name, address, auth_method
FROM pg_hba_file_rules
ORDER BY line_number;
pg_hba.conf 파일을 편집하여 인증 방식을 클라이언트와 호환되도록 맞춥니다.
# pg_hba.conf 예시
# TYPE DATABASE USER ADDRESS METHOD
host mydb myapp_user 192.168.1.0/24 scram-sha-256
host mydb myapp_user 10.0.0.0/8 md5
local all postgres peer
구버전 드라이버 호환을 위해 일시적으로 md5로 변경이 필요한 경우:
-- scram-sha-256으로 저장된 비밀번호를 md5로 재저장
SET password_encryption = 'md5';
ALTER ROLE myapp_user WITH PASSWORD 'NewSecurePassword!2024';
-- 설정 변경 후 반드시 pg_hba.conf reload 필요
SELECT pg_reload_conf();
원인 3: 역할(Role) 존재 여부 및 권한 확인
-- 해당 사용자(Role) 존재 여부 확인
SELECT rolname, rolcanlogin, rolvaliduntil, rolconnlimit
FROM pg_roles
WHERE rolname = 'myapp_user';
-- 존재하지 않는 경우 새로 생성
CREATE ROLE myapp_user WITH
LOGIN
PASSWORD 'SecurePassword!2024'
CONNECTION LIMIT 50
VALID UNTIL 'infinity';
-- LOGIN 권한이 없는 경우 부여
ALTER ROLE myapp_user WITH LOGIN;
-- 특정 데이터베이스에 대한 접근 권한 부여
GRANT CONNECT ON DATABASE mydb TO myapp_user;
-- 스키마 및 테이블 권한 확인
GRANT USAGE ON SCHEMA public TO myapp_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO myapp_user;
서버 로그에서 에러 상세 확인
-- 로그 파일 위치 확인
SHOW log_directory;
SHOW log_filename;
-- 현재 접속 실패 관련 로그 레벨 확인
SHOW log_connections;
SHOW log_disconnections;
-- 접속 로깅 활성화 (postgresql.conf 또는 ALTER SYSTEM)
ALTER SYSTEM SET log_connections = 'on';
ALTER SYSTEM SET log_disconnections = 'on';
SELECT pg_reload_conf();
예방 방법
- 비밀번호 관리 자동화 및 Secret Manager 도입
운영 환경에서는 AWS Secrets Manager, HashiCorp Vault, Azure Key Vault 등의 시크릿 관리 도구를 활용하여 데이터베이스 비밀번호를 중앙에서 관리하고, 비밀번호 교체 시 자동으로 애플리케이션에 반영되는 파이프라인을 구성하는 것이 Best Practice입니다. 이를 통해 비밀번호 변경 후 설정 파일 미업데이트로 인한 장애를 원천 차단할 수 있습니다.
“`sql
— 비밀번호 만료 기한을 설정하여 주기적 교체 강제화
ALTER ROLE myapp_user WITH PASSWORD ‘RotatedPassword!2024’
VALID UNTIL ‘2025-06-01’;
— 모든 사용자의 비밀번호 만료 기한 일괄 모니터링
SELECT rolname, rolvaliduntil,
CASE
WHEN rolvaliduntil < NOW() THEN '만료됨'
WHEN rolvaliduntil < NOW() + INTERVAL '30 days' THEN '30일 내 만료 예정'
ELSE ‘정상’
END AS status
FROM pg_roles
WHERE rolcanlogin = true
ORDER BY rolvaliduntil NULLS LAST;
“`
- 접속 실패 모니터링 및 알림 체계 구축
log_connections = on 설정과 함께 Prometheus + pg_stat_activity, Datadog, CloudWatch 등의 모니터링 도구를 연동하여 단위 시간당 접속 실패 횟수가 임계값을 초과하면 즉시 알림을 받을 수 있도록 구성합니다. 특히 동일 IP에서 반복적인 28P01 에러가 발생하는 경우 무차별 대입 공격(Brute Force Attack)의 가능성을 고려해야 하며, pg_hba.conf에서 해당 IP를 차단하거나 fail2ban 같은 도구와 연동하는 것을 권장합니다.
“`sql
— 현재 접속 중인 세션 및 대기 상태 모니터링
SELECT pid, usename, application_name, client_addr,
state, wait_event_type, wait_event, query_start
FROM pg_stat_activity
WHERE state != ‘idle’
ORDER BY query_start;
“`
관련 에러
28000(invalid_authorization_specification):28P01의 상위 에러 클래스로, 인증 관련 에러를 포괄합니다.pg_hba.conf에서 해당 호스트/사용자 조합이 아예 허용되지 않은 경우 발생합니다.3D000(invalid_catalog_name): 지정한 데이터베이스가 존재하지 않을 때 발생하며,28P01과 함께 접속 실패 시 동반되는 경우가 있습니다.08006(connection_failure): 네트워크 레벨에서의 접속 실패로, PostgreSQL 서버 자체가 응답하지 않을 때 발생합니다. 방화벽 설정이나pg_hba.conf설정 오류와 함께 확인해야 합니다.42501(insufficient_privilege): 인증은 성공했으나 해당 작업을 수행할 권한이 없을 때 발생하는 에러로,28P01해결 후 추가로 마주칠 수 있는 에러입니다.
주요 DBMS error code를 정리하는 시리즈입니다.
블로그 홈에서 다른 에러도 확인하세요.
본 포스트는 AI가 생성한 기술 가이드입니다. 운영 환경 적용 전 충분한 검토를 권장합니다.