장고 MySQL does not support unique constraints with conditions 에러 해결하기

소요 시간: 5분

오늘 프로젝트에서 Django로 작업하다가 조금 예상치 못한 경고 메시지를 마주했다. 상황은 이랬다.

오전 내내 Django 모델을 수정하고, 마이그레이션 작업을 끝낸 후 python manage.py migrate 명령어를 실행했다. 그런데 결과 메시지에 다음과 같은 경고가 뜬 것이다:

System check identified some issues:

WARNINGS:
account.EmailAddress: (models.W036) MySQL does not support unique constraints with conditions.
        HINT: A constraint won't be created. Silence this warning if you don't care about it.

처음에는 살짝 당황했다. MySQL이 조건부(unique) 제약 조건을 지원하지 않는다는 경고였다. 좀 더 정확히 말하자면, 특정 조건을 만족할 때만 고유성을 보장하는 제약 조건을 Django에서 설정했는데, MySQL은 이런 제약을 지원하지 않는다고 한다. 그래서 조건부 고유 제약 조건을 무시하고, 실제로는 제약이 생성되지 않는다는 뜻이었다.


결론적으로, 경고일 뿐이어서 프로젝트 자체가 망가지는 것은 아니지만, 이 상태로 두면 나중에 데이터 무결성 문제가 생길 수도 있다는 생각이 들었다.

문제를 해결하기 위해 선택할 수 있는 몇 가지 방법을 떠올려봤다:


그냥 경고 무시하기

사실 이 경고를 완전히 무시할 수도 있었다. 실제로 경고일 뿐이고, 필수적으로 오류를 해결하지 않아도 된다. 하지만 잠재적인 데이터 중복 문제를 감수해야 한다는 생각이 들었다.


모델에서 조건부 고유 제약 조건 제거

경고가 발생한 이유는 EmailAddress 모델에 고유 제약 조건을 설정할 때 특정 조건을 부여했기 때문이었다. 그래서 이 조건을 아예 제거하고, 모든 이메일 주소가 고유해야 한다는 기본 규칙으로 바꾸면 경고가 사라질 것이다. 이 방법이 현실적으로 가장 맞는 선택인 것 같았다.


데이터베이스 변경하기

MySQL 대신 PostgreSQL로 데이터베이스를 바꾸는 것도 한 가지 방법이었다. PostgreSQL은 조건부 고유 제약 조건을 지원하니까 말이다. 하지만 이미 MySQL을 사용하는 다른 부분이 많았고, DB를 변경하는 건 꽤나 큰 작업이 될 것 같아 이번엔 배제했다.

결국 2번 방법을 선택했다. EmailAddress 모델의 조건부 고유 제약 조건을 제거하고, 이메일 필드에 고유 제약 조건만 추가하는 식으로 수정했다. 코드 예시는 아래와 같다:

class EmailAddress(models.Model):
    email = models.EmailField(unique=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

그 후에 다시 마이그레이션을 진행했다:

python manage.py makemigrations
python manage.py migrate

결과적으로 경고는 사라졌고, 모든 것이 잘 작동했다. 이번 경험을 통해 Django와 MySQL 간의 제약 조건 차이를 좀 더 깊이 이해할 수 있었다. 코딩할 때는 예상치 못한 경고나 오류가 자주 발생하는데, 그런 상황에서 적절한 해결책을 찾는 것이 성장의 기회라는 생각이 든다.

오늘도 하나 배웠다! 

장고 리스트