무중단 배포에서 새 NOT NULL 컬럼에는 DB 기본값(db_default)을 준다
마이그레이션 뒤 아직 교체되지 않은 옛 코드는 새 컬럼을 모른다. 파이썬 default가 아니라 DB DEFAULT가 있어야 옛 코드의 INSERT가 깨지지 않는다.
무중단 배포 중에 null value in column ... violates not-null constraint 오류가 잠깐 쏟아지다 멎는다. 새 NOT NULL 컬럼을 추가한 배포였다.
무중단 배포는 마이그레이션을 먼저 돌리고 앱 서버를 하나씩 바꾼다. 그 사이 옛 코드가 도는 서버는 새 컬럼을 모르니 INSERT에 그 값을 넣지 않는다. Django 모델의 default=는 파이썬 쪽 기본값이라 새 코드에서만 채워진다. DB에는 기본값이 없으니 옛 코드의 INSERT는 NOT NULL에 걸린다.
Django 5부터는 db_default로 DB 자체에 기본값을 둘 수 있다. 파이썬 default와 함께 준다.
from django.db import models
from django.db.models import Value
class Profile(models.Model):
settings = models.JSONField(
default=dict,
db_default=Value({}, output_field=models.JSONField()),
)
is_beta = models.BooleanField(default=False, db_default=False)
마이그레이션 SQL이 실제로 ADD COLUMN ... DEFAULT ... NOT NULL이 되는지 확인한다.
python manage.py sqlmigrate accounts 0042
순서는 migrate → 앱 서버 하나씩 교체. 컬럼을 지우거나 이름을 바꾸는 일은 같은 배포에서 하지 않고, 코드가 더 이상 그 컬럼을 쓰지 않게 된 다음 배포에서 한다.