← 전체 글로 돌아가기

서버 운영

연결 문자열이 실제로 반영됐는지 서버에서 확인하기

DATABASE_URL 같은 환경 변수가 정말 적용됐는지, 운영 환경에서 확인하고 문제를 재현하는 방법.

서버 배포 후 DB 연결 문제가 생긴다. 로컬에선 멀쩡한데 운영에선 "connection refused" 같은 에러가 난다.

대부분 환경 변수가 제대로 전달되지 않았기 때문이다. Docker, Kubernetes, Dokploy, Vercel 등 배포 플랫폼마다 환경 변수를 설정하는 방식이 다르고, 간과하기 쉽다.

1단계: 서버에서 직접 환경 변수 확인

# Docker 컨테이너 내부
docker exec -it container-name bash
echo $DATABASE_URL

# 또는 Kubernetes Pod
kubectl exec -it pod-name -- env | grep DATABASE

# SSH로 접속한 서버
env | grep DATABASE

환경 변수가 진짜 설정됐는지 본다. 비워있으면 배포 설정에서 누락된 거다.

2단계: 앱에서 읽는 값이 뭔지 로깅

// 앱 시작 시 로깅 (프로덕션 로그에서 민감한 값은 마스킹)
const dbUrl = process.env.DATABASE_URL
if (!dbUrl) {
  console.error('DATABASE_URL not set')
  process.exit(1)
}
console.log('Connecting to:', dbUrl.replace(/:[^:@]+@/, ':***@'))

Actually가 읽은 값을 로그에 남긴다. 환경 변수는 있는데 값이 이상하면, 값을 일부 보여주면 된다. 물론 비밀번호는 마스킹한다.

3단계: 연결 테스트

# PostgreSQL
psql -h db-host -U username -d dbname -c "SELECT 1"

# MySQL
mysql -h db-host -u username -p -e "SELECT 1"

서버에서 직접 DB 연결을 테스트한다. 타임아웃, 인증 실패, 호스트 못 찾음 중 어느 것인지 알 수 있다.

4단계: 로컬과 환경 비교

# 로컬 .env 파일
cat .env | grep DATABASE_URL

# 배포된 환경
# (위의 1단계로 확인한 값)

같은 값인가? 다르다면 뭐가 다른가?

  • DB 호스트가 다름? (localhost vs 외부 IP)
  • 포트가 다름? (5432 vs 3306)
  • 데이터베이스명이 다름?
  • 인증 정보가 다름?

5단계: 환경 변수 설정 방식 확인

Docker/Docker Compose:

docker run -e DATABASE_URL="postgres://..." app

# 또는 docker-compose.yml
services:
  app:
    environment:
      DATABASE_URL: postgres://...

Kubernetes:

env:
  - name: DATABASE_URL
    valueFrom:
      secretKeyRef:
        name: db-secrets
        key: connection-string

Dokploy/배포 대시보드:

  • 환경 변수 섹션에 정말 입력했나?
  • 최근 배포에서 이 변수가 포함됐나?
  • "숨김" 처리된 변수는 값이 안 보이므로 기억에만 의존하기 쉬움

6단계: 재배포 전 상태 정리

# 기존 환경 변수 백업
env > /tmp/env_backup_$(date +%s).txt

# 새 환경 변수 확인
cat .env.production

# 배포
./deploy.sh

이전 배포의 환경 변수가 캐시되거나 남아있을 수 있다. 특히 컨테이너를 완전히 교체하지 않으면 오래된 환경 변수가 살아있을 수 있다.

7단계: 연결 풀 설정도 확인

// Prisma
const prisma = new PrismaClient({
  log: ['query', 'error']
})

// 또는 Node.js 드라이버
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  max: 20
})

연결 풀의 최대 연결 수가 너무 많으면 서버 리소스를 다 썼을 수도 있다. 또한 쿼리 로깅을 켜두면 실제로 어떤 데이터베이스에 연결했는지 로그에서 확인할 수 있다.

최소한 남겨둬야 할 증거

  • echo $DATABASE_URL 실행 결과 (마스킹)
  • DB 연결 테스트 결과 (성공/실패)
  • 앱 로그에서 연결 시도 메시지
  • 배포 설정에서 환경 변수 부분

이 네 가지로 문제 원인을 명확히 할 수 있다.