Django DB 연결 대기 커스텀 커맨드 제작 및 GitHub Actions 적용기
🎯 Mission 1: DB 연결을 위한 커스텀 명령어 생성하기
1️⃣ core 앱 생성
python manage.py startapp core
2️⃣ core 앱을 settings.py에 등록
# config/settings/base.py
INSTALLED_APPS = [
# ...
'core', # ✅ core 앱 추가
]
3️⃣ core/management/commands/wait_for_db.py 생성
mkdir -p core/management/commands
touch core/management/__init__.py
touch core/management/commands/__init__.py
touch core/management/commands/wait_for_db.py
4️⃣ 초기 wait_for_db.py 코드 작성
# 잘못된 초기 버전
import time
from django.db import connections
from django.db.utils import OperationalError
from django.core.management.base import BaseCommand
from psycopg2 import OperationalError as Psycopg2OpError
class Command(BaseCommand):
help = 'PostgreSQL DB가 준비될 때까지 기다립니다.'
def handle(self, *args, **options):
for i in range(10):
self.stdout.write(f'Try {i+1}: Waiting for database...')
try:
connection = connections['default']
if connection:
self.stdout.write(self.style.SUCCESS('✅ PostgreSQL DB 연결 성공!'))
return
except (Psycopg2OpError, OperationalError):
self.stdout.write(self.style.WARNING("⚠️ DB 연결 실패, 재시도 중..."))
time.sleep(1)
self.stdout.write(self.style.ERROR('❌ DB 연결 실패!'))
🚨 문제점: connections['default']는 객체 생성만 하며 실제 연결 테스트를 하지 않음.
DB가 꺼져 있어도 성공 메시지 출력되는 문제 발생.
✅ 수정된 wait_for_db.py
# 수정된 최종 버전
import time
from django.db import connections
from django.db.utils import OperationalError
from django.core.management.base import BaseCommand
from psycopg2 import OperationalError as Psycopg2OpError
class Command(BaseCommand):
help = 'PostgreSQL DB가 준비될 때까지 기다립니다.'
def handle(self, *args, **options):
max_attempts = 10
wait_seconds = 1
self.stdout.write(self.style.NOTICE('🚀 DB 연결 시도 시작!'))
for attempt in range(1, max_attempts + 1):
try:
db_conn = connections['default']
cursor = db_conn.cursor() # ✅ 진짜 연결 시도
cursor.execute('SELECT 1') # ✅ 쿼리 실행으로 실제 연결 확인
self.stdout.write(self.style.SUCCESS('✅ PostgreSQL DB 연결 성공!'))
return
except (Psycopg2OpError, OperationalError):
self.stdout.write(
self.style.WARNING(f'⚠️ {attempt}회차 연결 실패. {wait_seconds}초 후 재시도...')
)
time.sleep(wait_seconds)
self.stdout.write(self.style.ERROR('❌ DB 연결 실패! 최대 재시도 횟수 초과.'))
💡 개선된 포인트
- cursor.execute('SELECT 1') 추가로 진짜 DB 연결 확인
- 연결 실패 시 재시도 후 최대 10회 실패 시 종료
🎯 Mission 2: GitHub Actions에서 wait_for_db 적용하기
1️⃣ 기존 .github/workflows/checks.yml 문제
- name: Build and start containers
run: |
docker compose up -d --build
sleep 10 # ❌ 고정 시간 대기 (DB 준비 안 되면 실패)
🚨 문제점: sleep 10은 DB가 준비되었는지 모르고 단순히 10초만 기다림.
만약 DB가 10초 안에 준비 안 되면 CI 실패.
2️⃣ 수정된 .github/workflows/checks.yml
name: Code Quality Checks
on:
push:
branches:
- '**'
pull_request:
jobs:
ci:
runs-on: ubuntu-latest
services:
my-db:
image: postgres:14
env:
POSTGRES_USER: ${{ secrets.PG_USER }}
POSTGRES_PASSWORD: ${{ secrets.PG_PASSWORD }}
POSTGRES_DB: ${{ secrets.PG_NAME }}
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Build and start containers
run: |
docker compose up -d --build
- name: Wait for Database
run: docker compose exec my-django python manage.py wait_for_db
- name: Check code formatting with isort
run: docker compose exec my-django isort . --check --diff
- name: Check code formatting with black
run: docker compose exec my-django black . --check
- name: Apply migrations
run: docker compose exec my-django python manage.py migrate
- name: Run tests
run: docker compose exec my-django python manage.py test
- name: Cleanup containers
run: docker compose down --volumes --remove-orphans
💡 개선된 포인트
- sleep 10 삭제
- wait_for_db 커맨드를 실행하여 DB가 완전히 준비될 때까지 대기
- DB가 준비되지 않으면 자동 재시도하고 실패 시 에러 반환
✅ 우리가 디버깅하며 수정한 핵심 요약
문제수정
| connections['default']만 가져오면 DB 없이도 성공 | cursor.execute('SELECT 1')로 진짜 연결 확인 |
| GitHub Actions에서 sleep 10 고정 대기 | wait_for_db로 DB 준비될 때까지 정확하게 대기 |
🏁 최종 결과
- 로컬에서 DB 꺼진 상태에서도 정상적으로 10번 재시도 확인.
- GitHub Actions에서도 확실한 DB 준비 완료 후 테스트 진행 가능.
- CI/CD 실패율 대폭 감소 🎯
'프로젝트' 카테고리의 다른 글
| 🚩[3단계-1] 내 프로젝트 맞춰 만들어보는 API 스펙 (0) | 2025.06.09 |
|---|---|
| 📌 [3단계] DRF(Django REST Framework) 설치 및 Docker 적용 (0) | 2025.06.09 |
| 📮 3. Django ORM을 활용하여 Model 생성하기 (1) | 2025.06.09 |
| 📮 3. ERD를 구성 Mermid 활용 (0) | 2025.06.09 |
| 📮2. 데이터베이스 스키마 설계 (1) | 2025.06.09 |