소셜계정으로 회원가입한 유저 구분하기
제목을 커스텀 유저모델이라고 썼지만 사실 유저 인스턴스를 커스텀하는 것에 더 가깝다. 현재 만들고 있는 프로젝트에서 소셜계정
으로 로그인하는 유저에게 특정 필드값을 부여하고 싶었다. 예를 들면 네이버
로 로그인 하는 유저에게는 N
이라는 값을, 페이스북
으로 로그인하는 유저에게는 F
값을 주고 싶었다. 나중에 어떤 곳에서 유입이 더 많이 될지 살펴볼 수 있지 않을까?
처음에 혼란스러웠던 점은 어디서부터 시작해야 할지 모르겠다는 점이었다. 라이브러리 활용이 처음이었기 때문에 아예 백지 상태였다. 결론부터 말하자면
django-allauth
에 어딘가를 오버라이딩해야 한다.
django allauth custom usermodel이라고 검색하니 다시 공식문서로 회귀하게 되었다. 문서를 뒤져보니
Custom User Model
이라는 항목이 있었다. (http://django-allauth.readthedocs.io/en/latest/advanced.html)
공식문서를 확인해보니
DefaultAccountAdapter
도 있고,DefaultSocialAccountAdapter
라는 항목도 있었다. 둘의 차이점을 알기 위해서 직접 소스코드를 열어봐야 했다. 유저를 저장할 때 커스텀하고 싶었기 때문에save_user
메서드를 살펴봤다.
DefaultAccountAdapter
DefaultSocialAccountAdapter
하나는
form
을 이용한 회원가입을 할 때였다. 다른 하나는 소셜계정을 이용해 자동 회원가입(auto-signup)이 될 때save_user
메서드가 작동한다. 나는 소셜계정을 이용한 회원가입을 할 것이므로DefaultSocialAccountAdapter
을 활용해야 한다는 결론을 얻었다.
상속까지는 하겠는데, 다음은 오버라이딩이 문제였다. 해보지 않았기에 여러 시행착오들을 겪었다. 나의 개념부족을 탓해야지.
"""allauth를 통해서 유저를 저장할 때 호출됩니다. 유저 객체에 추가적인 정보를 담기 위해서 오버라이드를 실시했습니다."""user = .메소드 오버라이딩을 진행하기 위해서 이 글을 참조했다. 결론은 부모의 메서드를 불러오기 위해서
super()
를 활용해야 한다는 것이다.
이 메서드는 3개의 인자를 받는데,
request
,sociallogin,
form=None
이다. 딱봐도sociallogin
을 뒤져봐야 뭔가 나올것 같다는 느낌을 가져야한다.dir(sociallogin)
으로 일일이print
해서 뒤져보는 노가다를 했다.
dir(sociallogin)
여기서 다시 어떤걸 뒤져봐야 할지 감을 잡아야 한다. 나는 처음에 감이 안잡혀서 반을
dir()
로 확인해봤다. 그중 눈에 띈 것이account
라는 항목이었다. 한국어로 말하면계정
이다. 여기를 다시 뒤져본다.
dir(sociallogin.account):
오호, 여기까지 접근하니까 대충 DB에 저장되기 위한 어떤 것들이 모인다는 것을 짐작할 수 있다. 다시 뭘 골라야할까.
extra_data
였다. 이것을print
함수로 찍어보니까 드디어!! 원하는 결과값들이 전송되었따.
이제 비밀을 밝혀냈으니, 네이버 로그인인지, 페이스북 로그인인지 알아내야 했다.
이것은
sociallogin.account.proivder
에 숨어있었다. 이를 이용해서 뷰를 담음과 같이 작성했다.user = .social_app_name =if social_app_name == "FACEBOOK":elif social_app_name == "NAVER":
모델로 넘어와서
UserManager
를 커스텀했다.from django.contrib.auth.models import UserManager as DefaultUserManager# 페이스북으로 가입하면 user_type을 F(Facebook)으로 지정한다.user =user.user_type = "F"user.profile_image =return user# 네이버로 가입하면 user_type을 N(Naver)으로 지정한다. 그외에 커스텀 저장을 한다.user =user.username =user.nickname =user.email =user.first_name =user.last_name =user.profile_image =user.user_type = "N"return userfacebook이 주는 프로필 정보와, naver가 주는 프로필 정보가 달랐다. 따라서 입맛에 맞게 조정했다. 다소 방법이 좀 지저분해보이는데, 좀 더 좋은 의견 있으면 알려주시면 감사하겠습니다.
Adapter
소셜계정에는 페이스북도 있을 것이고, 네이버도 있을 것이고, 인스타그램도 있을 것이다. django-allauth
에서 다루는 소셜계정만 66개다(2017-07 기준). 소셜계정마다 회원가입을 다르게 처리하면 그것은 엄청난 소스코드 낭비다. 가장 핵심이 되는 회원가입 필드만을 모아서 회원가입을 공통으로 처리할 수 있는 어댑터가 필요하다. 결국 Adapter
로 모인다.
'프로그래밍 > Django' 카테고리의 다른 글
[Django] 네이버 영화 API 사용하기 (3) | 2017.09.22 |
---|---|
[Django] 폼(Form)에서 commit=False의 의미 (1) | 2017.07.29 |
[Django] Django-allauth를 통한 페이스북 회원가입 및 로그인 (2) | 2017.07.20 |
[DJango] AbstractBaseUser vs AbstractUser 비교하기 (0) | 2017.07.15 |
[Django] Django + Celery + Redis 이용하기 (5) | 2017.07.15 |