Enum
Python에서 열거형 상수를 관리할 때 Enum 클래스를 자주 사용합니다.
from enum import Enum
class StatusEnum(Enum):
PENDING = "Pending"
APPROVED = "Approved"
REJECTED = "Rejected"
Enum을 사용했을 때의 장점
• 코드 가독성 향상: 상수를 그룹화하여 일관된 코드를 작성
• 구조적 관리 가능: 열거형을 통해 상수로 관리하므로 코드의 유지보수성을 높임
하지만 Enum 클래스에는 몇 가지 단점이 있습니다.
1. value 속성을 통해 값에 접근해야 함
Python Enum에서 열거형 멤버는 객체로 동작하며 내부적으로 이름(name)과 값(value)을 속성으로 가지고 있습니다.
따라서 실제 값에 접근하려면 .value 속성을 사용해야 합니다.
아래와 같이 문자열과 열거형 멤버를 비교할 때 .value를 명시하지 않으면, 실제 값이 아닌 객체 자체를 비교하게 되어 올바른 결과를 얻지 못할 수 있습니다.
이러한 특성으로 value 누락 시 오류를 발생시키곤 합니다.
(이를 방지하기 위해 python 3.11 이후부터 Enum 대신 StrEnum을 사용할 수 있습니다.)
"Pending" == StatusEnum.PENDING
# False
"Pending" == StatusEnum.PENDING.value
# True
2. 모든 Enum 멤버의 값(value) 또는 이름(name)을 가져오기 어렵다
Enum 클래스에는 모든 멤버의 값이나 이름을 한 번에 가져오는 내장 메서드가 없습니다.
따라서 아래 예시와 같이 일일히 value들을 선언해줘야하는 번거로움이 존재하고 멤버가 많을수록 코드 가독성이 낮아지게 됩니다.
if status not in (StatusEnum.PENDING, StatusEnum.APPROVED, StatusEnum.REJECTED):
print("Invalid status.")
3. django 모델 필드와 호환되지 않음
django 모델 CharField의 choices 옵션으로 Enum 클래스를 지정할 수 없기 때문에 django에서 사용 시 한계가 존재합니다.
TextChoices
django는 Enum의 한계를 극복하기 위해 TextChoices 클래스를 제공합니다.
TextChoices django에서 는 상수를 보다 효율적으로 관리할 수 있으며, django 모델 필드와도 통합이 가능합니다.
from django.db import models
class StatusChoices(models.TextChoices):
PENDING = "Pending"
APPROVED = "Approved"
REJECTED = "Rejected"
1. .value 없이도 값에 접근 가능
TextChoices는 Enum클래스와 달리 .value 없이도 값을 가져올 수 있고 문자열과의 직접적인 비교가 가능합니다.
print(StatusChoices.PENDING)
# Pending
"Pending" == StatusChoices.PENDING
# True
2. 모든 멤버의 값 또는 이름 가져오기
또한 values()와 names() 메서드를 제공하여 정의된 모든 멤버의 값(value) 또는 이름(name)을 쉽게 가져올 수 있습니다.
print(StatusChoices.values())
# ['Pending', 'Approved', 'Rejected']
print(StatusChoices.names())
# ['PENDING', 'APPROVED', 'REJECTED']
3. Django 모델 필드와의 호환성
TextChoices는 Django 모델 필드에서 choices 옵션으로 사용할 수 있으며 django admin 페이지, form에서 옵션 사용이 가능합니다.
class Work(models.Model):
status = models.CharField(
max_length=20,
choices=StatusChoices.choices,
default=StatusChoices.PENDING,
)
works = Work.objects.filter(status=StatusChoices.APPROVED)
다만 필드 내부적인 validation은 따로 존재하지 않아 choices 이외의 다른 값을 저장하는 것은 가능합니다.
4. 가독성을 높이기 위한 레이블 제공
TextChoices는 각 멤버에 label을 지정할 수 있어 가독성을 높이며 admin 페이지나 폼에서도 표시가 가능합니다.
class StatusChoices(models.TextChoices):
PENDING = "Pending", "대기중"
APPROVED = "Approved", "승인됨"
REJECTED = "Rejected", "거부됨"
print(StatusChoices.PENDING.label)
# 대기중
'Django' 카테고리의 다른 글
Django 다중 서버 환경 동시성 제어하기(select_for_update/redis lock) (0) | 2025.02.23 |
---|---|
Django에서 JSON 파일로 동적 상수 클래스를 생성하기 (4) | 2025.02.01 |
FieldTracker와 Signals를 활용한 Django 모델 변경 로그 관리 (3) | 2024.12.29 |