SNS 로그인 오류
문제
카카오, 네이버, 구글 세 개 중 하나로 소셜로그인을 하고, 다른 계정으로 로그인하려고 할 시에 500 에러가 발생
예를 들어 카카오 로그인 > 로그아웃 > 구글 로그인을 하면 카카오 로그인은 정상적으로 작동하나 구글 로그인 시 500 에러, 이후 카카오 외에 어떤 로그인도 안 됨
데이터베이스를 삭제하고 반대로 다시 시도하면(구글 로그인 > 로그아웃 > 카카오 로그인) 구글 로그인만 됨
원인
에러코드 분석하기
HTTP GET /user/login/kakao/ 200 [0.01, 127.0.0.1:54412]
Internal Server Error: /user/login/kakao/
Traceback (most recent call last):
File "C:\Users\SCY\Desktop\DEV\TeamProject\ConnectMe\user\views.py", line 546, in SocialLogin
user = User.objects.get(email=email)
File "C:\Users\SCY\Desktop\DEV\TeamProject\ConnectMe\venv\lib\site-packages\django\db\models\manager.py", line 87, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\SCY\Desktop\DEV\TeamProject\ConnectMe\venv\lib\site-packages\django\db\models\query.py", line 637, in get
raise self.model.DoesNotExist(
user.models.User.DoesNotExist: User matching query does not exist.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
# *** 생략 ***
File "C:\Users\SCY\Desktop\DEV\TeamProject\ConnectMe\venv\lib\site-packages\MySQLdb\connections.py", line 254, in query
_mysql.connection.query(self, query)
MySQLdb.IntegrityError: (1062, "Duplicate entry '' for key 'user.account'")
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
# *** 생략 ***
_mysql.connection.query(self, query)
django.db.utils.IntegrityError: (1062, "Duplicate entry '' for key 'user.account'")
HTTP POST /user/login/kakao/ 500 [0.26, 127.0.0.1:54412]
1. 클라이언트가 HTTP GET 요청으로 "/user/login/kakao/" 엔드포인트 호출
2. status 200 > 성공
3. 따라서 오류는 /user/login/kakao/, 즉 KakaoLoginView 함수 (서버) 에러
4. user.models.User.DoesNotExist
예외 → user 객체를 가져오려고 시도했지만 해당 쿼리에 일치하는 사용자가 존재하지 않음
5. django.db.utils.IntegrityError
예외 → MySQL(데이터베이스)에서 "user.account" 키에 대해 중복된 값('')을 가진 항목이 이미 존재
6. 500 에러
MySQL 워크벤치
SNS 로그인을 하게되면 해당 유저가 있는지 이메일을 확인하고, 없으면 회원가입 후 로그인하게 된다.
이 때 소셜로그인은 아이디/비밀번호를 가져오지 않기 때문에 해당 필드가 공란이 된다.
그런데 account
필드는 unique=True
이기 때문에 공란이 중복되면 에러가 발생하는 것
해결방안
소셜로그인으로 회원가입을 할 때 account
를 채워주면 된다.
다른 서비스 등에서 같은 상황에 랜덤값으로 아이디를 만들어주는 것과 같은 맥락
1. 무작위 고유값으로 아이디를 부여하기 - 당첨!
2. 가져온 이메일을 아이디에도 넣기
해결
1. uuid4
를 사용해서 랜덤값을 생성하고 (ex 93ded08d-d014-4516-b46f-eb3078c8f351)
- uuid.uuid4()
2. ‘-’ 를 제거한 후 10글자 슬라이싱
- str(uuid.uuid4()).replace('-', '')[:10]
3. 해당 소셜 로그인 이니셜 넣기, 회원가입 시 account
에 해당 아이디 저장
구글
user_data = user_data.json()
new_account = 'G' + str(uuid.uuid4()).replace('-', '')[:10]
data = {
"account" : new_account,
"email": user_data.get("email"),
"nickname": user_data.get("name"),
"signup_type": "google",
"is_active" : True
}
카카오
user_data = user_data.json()
new_account = 'K' + str(uuid.uuid4()).replace('-', '')[:10]
data = {
"account" : new_account,
"email": user_data.get("kakao_account").get("email"),
"nickname": user_data.get("properties").get("nickname"),
"signup_type": "kakao",
"is_active" : True
}
서로 다른 계정으로 로그인해도 잘 되고, account도 잘 들어오는 것을 확인할 수 있당!
야호 💕
+ 소셜로그인 처음 구현해보는데 원래 이렇게 하루 꼬박 걸리는 거였나 싶고....
프로필 불러오기 실패
문제
프로필을 프론트랑 열심히 연결하고
html에 붙이기 전에 잘 불러와지는지 콘솔에 찍어봄
뭔가 잘못됐다 (아래 에러는 무시)
1. url을 봤을 때 원하는 유저의 user_id
(이 상황에선 로그인한 사용자의 user_id
) 는 잘 불러와짐
2. 백엔드에서 해당 url과 view 함수 연결 문제 없는 것 확인
3. {detail:’Not found.’}
라는 것을 보면 불러올 값이 없다는 것
4. 결론 : Profile
테이블에 해당 user_id
를 가진 값이 없다.
5. 이 사용자는 소셜로그인(구글 로그인) 상태이다.
혹시 몰라서 일반 회원가입 사용자로 로그인해 다시 찍어봄
원인
소셜로그인 함수에서 일반 회원가입과 마찬가지로 profile 객체를 같이 생성해야 하는데 그걸 누락함.
그래서 소셜로그인 사용자들은 User에만 있고 Profile은 없다…
해결
방법은 생각보다 간단하다.
소셜로그인 할 때 회원가입하는 부분에서 해당 유저의 profile을 만들어주기만 하면 끝.
일반 회원가입은 serializer에서 했었지만 소셜로그인은 없으니까..
# user/views.py
except User.DoesNotExist:
user = User.objects.create(**data)
user.set_unusable_password()
user.save()
# Profile 객체 생성
Profile.objects.create(user=user)
refresh = RefreshToken.for_user(user)
access_token = CustomTokenObtainPairSerializer.get_token(user)
return Response(
{"refresh": str(refresh), "access": str(access_token.access_token)},
status=status.HTTP_200_OK,
)
오늘도 얼렁뚱땅 감자의 하루 끝
GitHub 댓글