Django로 웹 서비스를 개발할 때 가장 중요한 결정 중 하나는 사용자 모델을 어떻게 구현할 것인가이다. Django는 세 가지 주요 방식을 제공하는데, 각 방식의 특징과 장단점을 살펴보고, 어떤 상황에서 어떤 방식을 선택해야 하는지 알아본다.
목차
1. 기본 User 모델 사용하기
Django의 django.contrib.auth.models에 정의된 기본 User 모델을 사용하는 방식이다.
특징
- username, password, email, first_name, last_name 등 기본적인 필드들이 미리 구현되어 있다.
- 인증 관련 메서드들이 모두 구현되어 있어 즉시 사용 가능하다.
- admin 페이지와의 통합이 즉시 가능하다.
- UserManager가 이미 구현되어 있어 별도 처리가 불필요하다.
장점
- 가장 빠르게 구현할 수 있다.
- Django의 기본 인증 시스템과 완벽하게 호환된다.
- 추가 설정 없이 바로 사용할 수 있다.
단점
- 커스터마이징이 제한적이다.
- 기본 필드를 수정하기 어렵다.
- username을 필수로 사용해야 한다.
추가 정보 관리: User Profile 패턴
기본 User 모델을 사용하면서 추가 정보를 관리해야 할 때는 OneToOneField를 사용한 Profile 모델(모델명은 자유롭게 명명 가능)을 생성하는 것이 일반적이다. 이를 'User Profile' 패턴이라고 한다.
아래 예시와 같이, User에 대한 추가 정보를 별도의 Profile 모델에 저장할 수 있다. Profile은 새로운 User가 생성되면 자동으로 생성된다.
from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
birth_date = models.DateField(null=True, blank=True)
phone_number = models.CharField(max_length=15, blank=True)
address = models.CharField(max_length=255, blank=True)
def __str__(self):
return f'{self.user.username} Profile'
# User 생성 시 자동으로 Profile 생성
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
이 패턴의 장단점은 다음과 같다:
장점
- 기존 User 모델을 그대로 사용할 수 있다.
- 추가 정보만 별도 테이블로 관리할 수 있다.
- User 모델의 기본 기능을 그대로 활용할 수 있다.
- Profile 모델의 수정이 용이하다.
단점
- 추가 쿼리가 발생할 수 있다.
- Profile 데이터 접근 시 user.profile과 같이 추가 참조가 필요하다.
- 데이터 일관성을 위한 관리가 필요하다.
2. AbstractUser 상속하기
Django의 django.contrib.auth.models에 정의된 AbstractUser를 사용하는 방식이다.
특징
- 기본 User 모델의 모든 필드와 메서드를 상속받는다.
- 기존 필드를 수정하고 새로운 필드를 추가할 수 있다.
- 기본 UserManager를 상속받아 사용하되, 필요한 경우 확장 가능하다.
장점
- 기본 User 모델의 모든 기능을 유지하면서 확장할 수 있다.
- admin 페이지와의 통합이 유지된다.
- 기존 인증 시스템을 그대로 사용할 수 있다.
단점
- username이 여전히 필수 필드이다.
- 데이터베이스 구조가 기본 User 모델과 비슷하게 유지된다.
- 인증 로직을 완전히 커스터마이징하기는 어렵다.
- 프로젝트 시작 시점에 설정해야 한다.
구현 예시
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
def create_user(self, username, email=None, password=None, **extra_fields):
# 커스텀 로직 추가
return super().create_user(username, email, password, **extra_fields)
birth_date = models.DateField(null=True, blank=True)
phone_number = models.CharField(max_length=15, blank=True)
3. AbstractBaseUser 상속하기
가장 유연한 커스터마이징이 가능한 방식이다.
특징
- 가장 기본적인 인증 기능만 제공한다.
- 모든 필드와 메서드를 직접 정의해야 한다.
- BaseUserManager도 함께 구현해야 한다.
- create_user()와 create_superuser() 메서드를 반드시 구현 필요하다.
- 비밀번호 해싱, 이메일 정규화 등을 직접 처리해야 한다.
- 사용자 생성 로직을 완전히 제어 가능하다.
장점
- 완전한 커스터마이징이 가능하다.
- 원하는 필드를 자유롭게 정의할 수 있다.
- username 대신 email 등 다른 필드를 인증 필드로 사용할 수 있다.
단점
- 많은 세부 구현이 필요하다.
- 인증 관련 모든 메서드를 직접 구현해야 한다.
구현 예시
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError('이메일은 필수입니다')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
return self.create_user(email, password, **extra_fields)
class CustomUser(AbstractBaseUser):
email = models.EmailField(unique=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
objects = CustomUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
어떤 방식을 선택해야 할까?
각 방식의 선택 기준을 정리하면 다음과 같다:
1. 기본 User 모델
- 빠른 개발이 필요할 때
- 기본 인증 시스템으로 충분할 때
- 커스터마이징이 거의 필요 없을 때
- 추가 정보는 Profile 모델로 관리 가능할 때
2. AbstractUser
- 기존 User 모델에 필드를 추가하고 싶을 때
- 기본 인증 시스템을 유지하면서 확장이 필요할 때
- username 기반 인증이 적합할 때
3. AbstractBaseUser
- 완전히 다른 인증 체계가 필요할 때
- email 기반 인증 등 특별한 인증 방식이 필요할 때
- 기존 User 모델의 필드가 대부분 불필요할 때
결론
Django에서 사용자 모델을 구현할 때는 프로젝트의 요구사항과 미래의 확장을 고려하여 신중하게 선택해야 한다. 특히 이 결정은 프로젝트 초기에 이루어지며, 나중에 변경하기가 매우 어렵다는 점을 염두에 두어야 한다.
간단한 프로젝트라면 기본 User 모델에 Profile 모델을 추가하는 것으로 충분할 수 있다. 하지만 복잡한 사용자 관리가 필요하거나, 특별한 인증 요구사항이 있다면 AbstractUser나 AbstractBaseUser의 사용을 고려해봐야 한다.
특별한 요구사항이 없다면 AbstractUser의 사용이 추천된다. 대부분의 커스터마이징 요구사항을 충족하면서도 Django의 기본 기능들을 그대로 활용할 수 있기 때문이다.
참고 자료
https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html
How to Extend Django User Model
The Django’s built-in authentication system is great. For the most part we can use it out-of-the-box, saving a lot ofdevelopment and testing effort. It fits ...
simpleisbetterthancomplex.com
'Django' 카테고리의 다른 글
[Django] 템플릿에 Bootstrap 적용하기 (0) | 2025.01.24 |
---|---|
[Django] Messages Framework (0) | 2025.01.23 |
[Django] View 클래스의 as_view() 메서드 (1) | 2025.01.20 |
[Django] 정적 파일(Static Files) 관리 (0) | 2025.01.17 |
[Django] urlpatterns의 작동 원리 (0) | 2024.12.29 |