상황
PostgreSQL에 접속하려는데 이런 에러가 뜬다.
FATAL: password authentication failed for user "myapp"
또는
FATAL: role "myapp" does not exist
또는
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed:
FATAL: Peer authentication failed for user "postgres"
전부 다르게 생겼지만 원인은 비슷한 경우가 많다. 하나씩 짚어보자.
원인 1: 비밀번호가 틀렸다 (가장 흔한 경우)
앱 설정 파일에 넣은 비밀번호와 실제 DB 비밀번호가 다른 거다. .env, application.yml, database.yml 등에서 비밀번호 오타나 환경별 혼용이 잦다.
확인 방법:
# postgres 유저로 직접 접속해서 비밀번호 재설정
sudo -u postgres psql
-- 현재 유저 목록 확인
\du
-- 비밀번호 재설정
ALTER USER myapp WITH PASSWORD 'newpassword';
원인 2: 유저 자체가 없다 (role does not exist)
DB는 있는데 유저를 만든 적이 없거나, 다른 환경에서 만든 유저가 이 환경에는 없는 경우다. 로컬에서 개발하다가 스테이징 DB로 붙으려 할 때 자주 발생한다.
해결:
-- postgres 슈퍼유저로 접속 후
CREATE USER myapp WITH PASSWORD 'yourpassword';
-- 데이터베이스 권한 부여
GRANT ALL PRIVILEGES ON DATABASE mydb TO myapp;
-- 스키마 권한도 줘야 하는 경우
GRANT ALL ON SCHEMA public TO myapp;
원인 3: pg_hba.conf 인증 방식 문제 (Peer auth failed)
Peer authentication failed 에러는 pg_hba.conf의 인증 방식 설정 문제다. 로컬 소켓 접속 시 OS 유저명과 DB 유저명이 같아야 하는 peer 방식으로 설정돼 있을 때 발생한다.
pg_hba.conf 위치 확인:
sudo -u postgres psql -c "SHOW hba_file;"
# 보통 /etc/postgresql/14/main/pg_hba.conf 또는 /var/lib/pgsql/data/pg_hba.conf
pg_hba.conf 수정:
sudo nano /etc/postgresql/14/main/pg_hba.conf
수정 전:
local all all peer
수정 후 (비밀번호 인증으로 변경):
local all all md5
또는 특정 유저만:
local mydb myapp md5
host mydb myapp 127.0.0.1/32 md5
변경 후 재시작:
sudo systemctl restart postgresql
원인 4: Docker 환경에서 환경변수 미전달
Docker로 PostgreSQL 띄울 때 POSTGRES_PASSWORD 없이 컨테이너를 올리거나, 앱 컨테이너에 DB 접속 정보를 제대로 안 넘긴 경우다.
# docker-compose.yml 올바른 예시
services:
db:
image: postgres:16
environment:
POSTGRES_DB: mydb
POSTGRES_USER: myapp
POSTGRES_PASSWORD: mypassword
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U myapp -d mydb"]
interval: 5s
timeout: 5s
retries: 5
app:
build: .
environment:
DATABASE_URL: postgresql://myapp:mypassword@db:5432/mydb
depends_on:
db:
condition: service_healthy
depends_on은 컨테이너 시작 순서만 보장한다. PostgreSQL이 실제로 준비됐는지는 healthcheck와 condition: service_healthy로 처리해야 한다.
원인 5: 접속 호스트/포트 오류
Connection refused는 PostgreSQL이 해당 주소에서 리슨하고 있지 않다는 뜻이다.
# PostgreSQL이 실제로 떠 있는지
sudo systemctl status postgresql
# 어느 포트에서 리슨 중인지
sudo ss -tlnp | grep 5432
# 외부 접속 허용 설정 확인
sudo grep listen_addresses /etc/postgresql/14/main/postgresql.conf
외부에서 접속하려면 postgresql.conf에서:
listen_addresses = '*'
그리고 pg_hba.conf에도 원격 접속 허용 라인 추가:
host all all 0.0.0.0/0 md5
상황별 체크리스트
| 증상 | 확인할 것 | 해결책 |
|---|---|---|
password authentication failed | 비밀번호 오타, 환경 혼용 | ALTER USER ... WITH PASSWORD |
role does not exist | 유저 미생성 | CREATE USER + 권한 부여 |
Peer authentication failed | pg_hba.conf 설정 | peer → md5 변경 후 재시작 |
Connection refused | PostgreSQL 미실행 또는 포트 불일치 | 서비스 상태 확인, listen_addresses 설정 |
| Docker에서만 발생 | 컨테이너 간 네트워크, 환경변수 | db 호스트명 사용, healthcheck 추가 |
Node.js 접속 예시 (pg 라이브러리)
const { Pool } = require('pg');
const pool = new Pool({
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT || '5432'),
database: process.env.DB_NAME,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
ssl: process.env.DB_SSL === 'true' ? { rejectUnauthorized: false } : false,
connectionTimeoutMillis: 5000,
idleTimeoutMillis: 30000,
max: 10,
});
pool.query('SELECT NOW()', (err, res) => {
if (err) {
console.error('DB 연결 실패:', err.message);
} else {
console.log('DB 연결 성공:', res.rows[0].now);
}
});
Python (psycopg2, SQLAlchemy)
import psycopg2
from psycopg2 import OperationalError
import os
def create_connection():
try:
conn = psycopg2.connect(
host=os.getenv("DB_HOST", "localhost"),
port=int(os.getenv("DB_PORT", 5432)),
database=os.getenv("DB_NAME"),
user=os.getenv("DB_USER"),
password=os.getenv("DB_PASSWORD"),
)
print("PostgreSQL 연결 성공")
return conn
except OperationalError as e:
print(f"연결 실패: {e}")
raise
from sqlalchemy import create_engine
DATABASE_URL = os.getenv("DATABASE_URL")
engine = create_engine(DATABASE_URL, pool_pre_ping=True, pool_recycle=3600)
마무리
PostgreSQL 접속 에러는 대부분 세 가지다: 비밀번호 틀림, 유저 없음, pg_hba.conf 설정 문제. 에러 메시지를 정확히 읽으면 원인이 나온다. FATAL: 뒤에 오는 텍스트가 전부다. Connection refused는 PostgreSQL 자체가 안 떠있거나 포트가 다른 거고, authentication failed는 자격증명 문제, role does not exist는 유저 생성을 안 한 거다.
Docker 환경이면 컨테이너 간 네트워크와 healthcheck까지 챙겨야 한다.
댓글 없음:
댓글 쓰기