| name | django-verification |
| description | Django 프로젝트를 위한 검증 루프: 배포나 PR 전 마이그레이션, 린팅, 커버리지가 포함된 테스트, 보안 스캔 및 배포 준비 상태를 점검합니다. |
| origin | ECC |
Django 검증 루프 (Verification Loop)
PR 전, 주요 변경 후, 그리고 배포 전에 실행하여 Django 애플리케이션의 품질과 보안을 보장합니다.
활성화 시점
- Django 프로젝트에서 풀 리퀘스트(PR)를 보내기 전
- 주요 모델 변경, 마이그레이션 업데이트 또는 의존성 업그레이드 후
- 스테이징 또는 프로덕션 배포 전 검증 시
- 환경 확인 → 린트 → 테스트 → 보안 → 배포 준비 파이프라인 전체를 실행할 때
- 마이그레이션 안정성 및 테스트 커버리지를 검증할 때
1단계: 환경 확인
python --version
which python
pip list --outdated
python -c "import os; import environ; print('DJANGO_SECRET_KEY set' if os.environ.get('DJANGO_SECRET_KEY') else 'MISSING: DJANGO_SECRET_KEY')"
환경 설정이 잘못된 경우, 중단하고 수정하세요.
2단계: 코드 품질 및 포맷팅
mypy . --config-file pyproject.toml
ruff check . --fix
black . --check
black .
isort . --check-only
isort .
python manage.py check --deploy
흔히 발생하는 문제:
- 공개 함수에 타입 힌트 누락
- PEP 8 포맷팅 위반
- 정렬되지 않은 임포트 구문
- 프로덕션 설정에 Debug 설정이 남은 경우
3단계: 마이그레이션
python manage.py showmigrations
python manage.py makemigrations --check
python manage.py migrate --plan
python manage.py migrate
python manage.py makemigrations --merge
보고 항목:
- 대기 중인 마이그레이션 수
- 마이그레이션 충돌 여부
- 마이그레이션이 없는 모델 변경 사항
4단계: 테스트 + 커버리지
pytest --cov=apps --cov-report=html --cov-report=term-missing --reuse-db
pytest apps/users/tests/
pytest -m "not slow"
pytest -m integration
open htmlcov/index.html
보고 항목:
- 전체 테스트 결과: X 통과, Y 실패, Z 건너뜀
- 전체 커버리지: XX%
- 앱별 커버리지 상세 내역
커버리지 목표:
| 컴포넌트 | 목표 |
|---|
| Models | 90%+ |
| Serializers | 85%+ |
| Views | 80%+ |
| Services | 90%+ |
| 전체 | 80%+ |
5단계: 보안 스캔
pip-audit
safety check --full-report
python manage.py check --deploy
bandit -r . -f json -o bandit-report.json
gitleaks detect --source . --verbose
python -c "from django.core.exceptions import ImproperlyConfigured; from django.conf import settings; settings.DEBUG"
보고 항목:
- 취약한 의존성 발견 여부
- 보안 설정 문제
- 하드코딩된 시크릿 감지 여부
- DEBUG 모드 상태 (프로덕션에서는 False여야 함)
6단계: Django 관리 명령
python manage.py check
python manage.py collectstatic --noinput --clear
echo "from apps.users.models import User; User.objects.create_superuser('admin@example.com', 'admin')" | python manage.py shell
python manage.py check --database default
python -c "from django.core.cache import cache; cache.set('test', 'value', 10); print(cache.get('test'))"
7단계: 성능 체크
django-admin debugsqlshell
python manage.py shell << EOF
from django.db import connection
with connection.cursor() as cursor:
cursor.execute("SELECT table_name, index_name FROM information_schema.statistics WHERE table_schema = 'public'")
print(cursor.fetchall())
EOF
보고 항목:
- 페이지당 쿼리 수 (일반적인 페이지의 경우 50개 미만 권장)
- 누락된 데이터베이스 인덱스
- 감지된 중복 쿼리
8단계: 정적 자산(Static Assets)
npm audit
npm audit fix
npm run build
ls -la staticfiles/
python manage.py findstatic css/style.css
9단계: 설정 리뷰
python manage.py shell << EOF
from django.conf import settings
import os
checks = {
'DEBUG is False': not settings.DEBUG,
'SECRET_KEY set': bool(settings.SECRET_KEY and len(settings.SECRET_KEY) > 30),
'ALLOWED_HOSTS set': len(settings.ALLOWED_HOSTS) > 0,
'HTTPS enabled': getattr(settings, 'SECURE_SSL_REDIRECT', False),
'HSTS enabled': getattr(settings, 'SECURE_HSTS_SECONDS', 0) > 0,
'Database configured': settings.DATABASES['default']['ENGINE'] != 'django.db.backends.sqlite3',
}
for check, result in checks.items():
status = '✓' if result else '✗'
print(f"{status} {check}")
EOF
10단계: 로깅 설정 확인
python manage.py shell << EOF
import logging
logger = logging.getLogger('django')
logger.warning('Test warning message')
logger.error('Test error message')
EOF
tail -f /var/log/django/django.log
11단계: API 문서 확인 (DRF 사용 시)
python manage.py generateschema --format openapi-json > schema.json
python -c "import json; json.load(open('schema.json'))"
12단계: 변경 사항(Diff) 리뷰
git diff --stat
git diff
git diff --name-only
git diff | grep -i "todo\|fixme\|hack\|xxx"
git diff | grep "print("
git diff | grep "DEBUG = True"
git diff | grep "import pdb"
체크리스트:
- 디버깅 문구 없음 (print, pdb, breakpoint())
- 중요 코드에 TODO/FIXME 주석 없음
- 하드코딩된 시크릿이나 자격 증명 없음
- 모델 변경에 따른 데이터베이스 마이그레이션 포함됨
- 설정 변경 사항이 문서화됨
- 외부 호출에 대한 에러 처리 구현됨
- 필요한 곳에 트랜잭션 관리 적용됨
리포트 템플릿 예시
DJANGO 검증 리포트
==========================
1단계: 환경 확인
✓ Python 3.11.5
✓ 가상 환경 활성화됨
✓ 모든 환경 변수 설정됨
2단계: 코드 품질
✓ mypy: 타입 에러 없음
✗ ruff: 3개 이슈 발견 (자동 수정됨)
✓ black: 포맷팅 이슈 없음
✓ isort: 임포트 정렬 완료
✓ manage.py check: 이슈 없음
3단계: 마이그레이션
✓ 적용되지 않은 마이그레이션 없음
✓ 마이그레이션 충돌 없음
✓ 모든 모델에 마이그레이션 존재함
4단계: 테스트 + 커버리지
테스트: 247 통과, 0 실패, 5 건너뜀
커버리지:
전체: 87%
users: 92%
products: 89%
orders: 85%
payments: 91%
5단계: 보안 스캔
✗ pip-audit: 2개 취약점 발견 (수정 필요)
✓ safety check: 이슈 없음
✓ bandit: 보안 이슈 없음
✓ 시크릿 감지되지 않음
✓ DEBUG = False
6단계: Django 명령
✓ collectstatic 완료
✓ 데이터베이스 무결성 OK
✓ 캐시 백엔드 연결 가능
7단계: 성능
✓ N+1 쿼리 감지되지 않음
✓ 데이터베이스 인덱스 설정됨
✓ 쿼리 수 적정함
8단계: 정적 자산
✓ npm audit: 취약점 없음
✓ 자산 빌드 성공
✓ 정적 파일 수집 완료
9단계: 설정
✓ DEBUG = False
✓ SECRET_KEY 설정됨
✓ ALLOWED_HOSTS 설정됨
✓ HTTPS 활성화됨
✓ HSTS 활성화됨
✓ 데이터베이스 설정됨
10단계: 로깅
✓ 로깅 설정됨
✓ 로그 파일 쓰기 가능
11단계: API 문서
✓ 스키마 생성됨
✓ Swagger UI 접근 가능
12단계: 변경 사항 리뷰
변경된 파일: 12개
+450, -120 라인
✓ 디버그 문구 없음
✓ 하드코딩된 시크릿 없음
✓ 마이그레이션 포함됨
권장 사항: 경고: 배포 전 pip-audit 취약점을 수정하세요.
다음 단계:
1. 취약한 의존성 업데이트
2. 보안 스캔 재실행
3. 최종 테스트를 위해 스테이징 환경에 배포
배포 전 체크리스트
지속적 통합 (CI)
GitHub Actions 예시
name: Django Verification
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Cache pip
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
- name: Install
빠른 참조
| 확인 사항 | 명령어 |
|---|
| 환경 | python --version |
| 타입 체크 | mypy . |
| 린팅 | ruff check . |
| 포맷팅 | black . --check |
| 마이그레이션 | python manage.py makemigrations --check |
| 테스트 | pytest --cov=apps |
| 보안 | pip-audit && bandit -r . |
| Django 체크 | python manage.py check --deploy |
| 정적 파일 수집 | python manage.py collectstatic --noinput |
| 변경 통계 | git diff --stat |
기억하세요: 자동화된 검증은 일반적인 문제를 잡아내지만, 수동 코드 리뷰와 스테이징 환경에서의 테스트를 대신할 수는 없습니다.