안녕하세요! 오늘은 Django REST Framework를 사용하여 구현한 종합적인 사용자 인증 시스템에 대해 알아보겠습니다. 이 시스템은 회원가입, 로그인, 카카오 소셜 로그인, 로그아웃, 비밀번호 재설정 등의 기능을 포함하고 있습니다. 각 기능별로 코드와 함께 자세히 설명드리겠습니다.
회원가입 기능은 UserRegistrationView 클래스에서 구현됩니다.
class UserRegistrationView(generics.CreateAPIView):
queryset = CustomUser.objects.all()
serializer_class = RegisterSerializer
permission_classes = [AllowAny]
authentication_classes = []
@extend_schema(
summary="사용자 회원가입",
description="새로운 사용자 계정을 생성하고 JWT TOKEN 발급 (비밀번호는 8자 이상 20자 이하)",
# ... (생략)
)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
refresh = RefreshToken.for_user(user)
return Response({
"message": "회원가입이 성공적으로 완료되었습니다",
"username": user.username,
"email": user.email,
"refresh": str(refresh),
"access": str(refresh.access_token),
}, status=status.HTTP_201_CREATED)
return Response({
"message": "회원가입에 실패하셨습니다.",
"errors": serializer.errors
}, status=status.HTTP_400_BAD_REQUEST)
이 뷰는 새로운 사용자 계정을 생성하고 JWT 토큰을 발급합니다. RegisterSerializer를 사용하여 입력 데이터의 유효성을 검사하고, 유효한 경우 사용자를 생성합니다. 성공 시 201 상태 코드와 함께 사용자 정보 및 토큰을 반환합니다.
로그인 기능은 UserLoginView 클래스에서 구현됩니다.
class UserLoginView(APIView):
permission_classes = [AllowAny]
authentication_classes = []
@extend_schema(
summary="사용자 로그인",
description="사용자 인증 및 JWT 토큰 발급",
# ... (생략)
)
def post(self, request):
serializer = LoginSerializer(data=request.data)
if serializer.is_valid():
user = serializer.validated_data['user']
refresh = RefreshToken.for_user(user)
return Response({
"message": "로그인이 성공적으로 완료되었습니다.",
"email": user.email,
"username": user.username,
"refresh": str(refresh),
"access": str(refresh.access_token),
}, status=status.HTTP_200_OK)
return Response({
"message": "로그인에 실패하셨습니다.",
"errors": serializer.errors
}, status=status.HTTP_400_BAD_REQUEST)
이 뷰는 사용자 인증을 처리하고 로그인 성공 시 JWT 토큰을 발급합니다. LoginSerializer를 사용하여 이메일과 비밀번호를 검증하고, 인증 성공 시 토큰을 생성하여 반환합니다.
카카오 소셜 로그인은 두 개의 뷰로 구현됩니다: KakaoLoginView와 KakaoCallbackView.
class KakaoLoginView(APIView):
permission_classes = [AllowAny]
@extend_schema(
summary="카카오 로그인 URL 요청",
description="카카오 로그인을 위한 인증 URL을 반환합니다.",
responses={200: OpenApiTypes.OBJECT}
)
def get(self, request):
kakao_auth_url = f"https://kauth.kakao.com/oauth/authorize?client_id={settings.KAKAO_REST_API_KEY}&redirect_uri={settings.KAKAO_REDIRECT_URI}&response_type=code"
return Response({"auth_url": kakao_auth_url})
class KakaoCallbackView(APIView):
permission_classes = [AllowAny]
@extend_schema(
summary="카카오 로그인 콜백 처리",
description="카카오 로그인 후 받은 코드로 사용자 정보를 조회하고 로그인 처리합니다.",
# ... (생략)
)
def get(self, request):
code = request.GET.get('code')
# 카카오 액세스 토큰 요청
# ... (생략)
# 카카오 사용자 정보 요청
# ... (생략)
# 사용자 생성 또는 조회
# ... (생략)
# JWT 토큰 생성
refresh = RefreshToken.for_user(user)
user.refresh_token = str(refresh)
user.save()
return Response({
"user": UserSerializer(user).data,
"access_token": str(refresh.access_token),
"refresh_token": str(refresh),
})
KakaoLoginView는 카카오 로그인 URL을 제공하고, KakaoCallbackView는 카카오 인증 후 콜백을 처리합니다. 카카오 API를 통해 사용자 정보를 받아와 계정을 생성하거나 조회하고, JWT 토큰을 발급합니다. (Kakao 소셜로그인에 관한 자세한 글은 따로 올리는 걸로....)
로그아웃 기능은 LogoutView 클래스에서 구현됩니다.
class LogoutView(APIView):
authentication_classes = [JWTAuthentication]
@extend_schema(
summary="사용자 로그아웃",
description="사용자의 리프레시 토큰을 무효화합니다.",
responses={200: OpenApiTypes.OBJECT}
)
def post(self, request):
user = request.user
user.refresh_token = ""
user.save()
return Response({"message": "Successfully logged out."}, status=status.HTTP_200_OK)
이 뷰는 JWT 인증을 사용하여 현재 로그인한 사용자를 식별하고, 사용자의 리프레시 토큰을 무효화합니다.
비밀번호 재설정 기능은 RequestPasswordResetView와 SetNewPasswordView 클래스에서 구현됩니다.
class RequestPasswordResetView(APIView):
permission_classes = [AllowAny]
@extend_schema(
summary="비밀번호 재설정 요청",
description="사용자 이메일로 비밀번호 재설정 링크를 발송합니다.",
# ... (생략)
)
def post(self, request):
serializer = NewPasswordSerializer(data=request.data)
if serializer.is_valid():
email = serializer.validated_data['email']
# ... (생략: 사용자 조회 및 이메일 발송 로직)
return Response({'message': '비밀번호 재설정 이메일을 발송했습니다.'}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class SetNewPasswordView(APIView):
permission_classes = [AllowAny]
@extend_schema(
summary="새 비밀번호 설정",
description="비밀번호 재설정 링크를 통해 새 비밀번호를 설정합니다.",
# ... (생략)
)
def post(self, request):
serializer = SetNewPasswordSerializer(data=request.data)
if serializer.is_valid():
# ... (생략: 토큰 검증 및 비밀번호 재설정 로직)
return Response({'message': '비밀번호가 성공적으로 재설정되었습니다.'}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
RequestPasswordResetView는 사용자 이메일로 비밀번호 재설정 링크를 발송하고, SetNewPasswordView는 재설정 링크를 통해 새 비밀번호를 설정합니다.
이 Django REST Framework 기반의 인증 시스템은 현대적인 웹 애플리케이션에서 요구되는 대부분의 인증 기능을 포괄적으로 다루고 있습니다. JWT를 사용한 인증, 소셜 로그인 지원, 안전한 비밀번호 재설정 메커니즘 등을 통해 보안성과 사용자 편의성을 모두 고려했습니다.
이 시스템은 DRF의 APIView와 generics를 사용하여 구현되어 있어 확장성이 뛰어나며, drf-spectacular를 통한 API 문서화로 개발자 경험도 향상시켰습니다.
여러분의 프로젝트에 이러한 인증 시스템을 도입하면 안전하고 사용자 친화적인 로그인 경험을 제공할 수 있을 것입니다.
자세한 코드는 깃허브에~⭐️ [Project name: pollloop]