⚠️

아래 공식문서를 읽고 인증 관련된 내용 중 일부만 발췌해서 정리했습니다.

자세한 내용이 궁금하시다면 공식문서를 참고하시는 것을 추천드립니다. 

https://docs.djangoproject.com/en/5.0/topics/auth/customizing/

 

Django

The web framework for perfectionists with deadlines.

docs.djangoproject.com

 

✅custom user model 설정하기

 

settings.py 파일의 AUTH_USER_MODEL 변수의 값을 "app이름.Model이름" 으로 설정하자. 

AUTH_USER_MODEL = "account.CustomUser"

 

또한 공식문서에서는 인증 모델의 정보에 접근할 때는 쿼리셋을 작성할 때 흔히 사용하는 방식(CustomUser.objects....) 보다는 django.contrib.auth 모듈의 get_user_model() 사용을 권장한다. 

 

이유는 다른 auth user model을 사용하는 다른 프로젝트에서 코드를 사용할 때 충돌이 날 수 있어서라고 한다. 

 

확장성 있는 코드를 작성하고 싶다면 공식문서대로 하는 것이 좋겠고, 다른 프로젝트에서 코드를 사용할 일이 없다면 크게 상관없지 않을까 싶다. 

 

✅인증 정보 구분하기: profile model, proxy model

공식 문서에서는 인증 관련 정보는 user 모델에, 유저와 관련된 그 외 다른 정보는 다른 모델(profile model)에 저장하는 것을 권장한다. 

 

예를 들어 profile model이 Employee라고 하면, Employee와 User 모델의 관계를 1:1 또는 외래키로 설정하는 것이다. 

class Employee(models.Model):
	user = models.OneToOneField(User)
	...

 

반면 인증 관련 정보 외에 추가로 정보를 저장할 필요는 없지만 User 모델이 동작하는 방식을 바꾸고 싶다면 proxy model을 사용하는 것도 좋다. 

 

프록시 모델(proxy model)을 사용하면 유저 모델에서 사용 가능한 메소드나 쿼리셋의 정렬 등을 유저 모델과 다르게 설정할 수 있다. 

class Member(CustomUser):

	class Meta:
		proxy = True

 

✅User model Customizing

공식문서에서는 유저 모델을 정의할 때 django.contrib.auth.models 모듈의 AbstractBaseUser를 상속해서 사용하는 것을 권장한다. 

 

AbstractUser는 장고의 기본 유저 모델인 만큼 인증에서 사용할 수 있는 여러 메소드가 정의되어 있기 때문이다. 

 

물론 AbstractUser를 상속하지 않고도 유저 모델을 새로 정의해서 사용하는 것도 가능하다. 

 

하지만 이 경우 AbstractUser에 있던 기본 메소드들을 따로 정의해 주어야 하기 때문에 불편할 수도 있다. 

 

AbstractUser 모델을 상속해서 커스터마이징 할 경우, 다음과 같은 필드를 설정할 때는 주의해야 한다. 

 

USERNAME_FIELD

각 유저를 unique하게 인식하기 위해 필요한 필드이다. 이 값으로 선언한 필드는 반드시 unique 해야 한다. 

 

REQUIRED_FIELDS

createsuperuser 커맨드를 호출할 때는 이 필드들의 값을 모두 입력해야 한다. 이 필드값들은 unique 할 필요는 없지만 blank=False 이어야 한다. 

class CustomUser(AbstractUser):
	...
	email = models.CharField(max_length=40, unique=True)
    
	USERNAME_FIELD = "email"
	REQUIRED_FIELDS = ["email", "address"]

 

☑️blank와 null의 차이

null은 DB에 값을 저장할 때 null을 허용할지를 결정하고, blank은 DB와는 관련 없는 validation의 영역이다. null=True이어도 blank=False라면 DB에 넣을 값을 검사할 때 허용되지 않는다. 

 

그 외에도 AbstractBaseUser에는 세션이나 비밀번호 설정 등과 관련한 여러 메소드를 제공한다. 

 

is_authenticated

요청을 한 유저가 인증된 유저인지를 boolean 값으로 리턴한다. 

다만 이 값이 True라고 해도 이 유저가 어떤 특정 권한이 있거나 이 유저에 대한 세션이 있는지는 보장하지 않는다. 

 

set_password()

장고에서는 유저의 비밀번호 값을 그대로 저장하지 않고 암호화하여 저장하기 때문에 password의 값을 그대로 바꾸면 로그인이 되지 않는다. 

그 대신 set_password() 함수를 사용하면 해당 값이 암호화되어 저장된다. 

 

set_unusable_password()

장고에서 비밀번호를 사용하지 않을 때도 이 메소드를 사용하면 좋다. 

비밀번호에 공백 값을 넣는 것과 비밀번호를 사용하지 않는 것은 다른데, 이 메소드는 후자일 경우에 사용하자. 

 

get_session_auth_hash()

유저의 비밀번호를 HMAC 방식으로 암호화한 값을 리턴한다. (정확히 어떤 데 쓰이는지는 아직 모르겠다...)

 

 

☑️AbstractUser

만약 유저 모델의 특성을 거의 바꿀 것 같지 않다면 AbstractBaseUser를 상속한 AbstractUser 모델을 그대로 사용하는 것도 가능하다. 

 

이 모델에서는 USERNAME_FIELDREQUIRED_FIELDS 옵션도 이미 정의되어 있다.

 

AbstractBaseUser의 설정을 대부분 따르되 그 중 일부만 변경하고 싶다면 AbstractUser를 사용하면 코드를 간결하게 작성할 수 있다. 

class CustomUser(AbstractUser):
	pass

 

✅User manager Customizing

기본적으로, 각 모델에는 objects라는 이름을 가진 manager 클래스가 있다. 

 

이 manager 클래스는 모델이 어떤 쿼리를 통해서 데이터베이스와 어떻게 상호작용할지를 결정하는 일종의 인터페이스 역할을 한다. 

 

 

☑️BaseManager

 

유저 모델의 manager 클래스는 django.contrib.auth.models 모듈의 BaseManager 클래스를 상속한다. 

 

get_by_natural_key()

BaseManager에서 유저를 찾는 데 사용하는 메소드이다. 

createsuperuser 등의 커맨드에서도 호출된다. 

유저에서 USERNAME_FIELD로 선언한 필드의 값을 사용해서 유저를 찾는다.

 

 

☑️CustomManager

 

이 클래스를 상속해서 커스텀 manager 클래스를 만들고 싶다면 두 가지 메소드를 재정의해야 한다. 

 

create_user()

유저를 생성할 때 호출되는 메소드이다.

유저 모델에서 USERNAME_FIELDREQUIRED_FIELDS로 선언한 필드들은 모두 매개변수로 받아야 한다. 

 

create_superuser()

createsuperuser 커맨드를 사용할 때 호출된다. 

마찬가지로 USERNAME_FIELDREQUIRED_FIELDS로 선언한 필드들은 모두 매개변수로 받아야 한다. 

 

 

참고한 포스트

https://docs.djangoproject.com/en/5.0/ref/models/fields/#:~:text=null%20is%20purely%20database%2Drelated,the%20field%20will%20be%20required.

https://docs.djangoproject.com/en/5.0/topics/db/managers/

 

'server-side > Django' 카테고리의 다른 글

django customizing authentication  (0) 2024.01.07
django sessions  (0) 2024.01.06
django migrations  (0) 2023.12.31
django routers  (1) 2023.12.21
django apps  (0) 2023.12.20

+ Recent posts