ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Django DRF 개인과제 트러블 슈팅
    Django 2024. 9. 10. 17:21

    Django DRF 트러블 슈팅

     

    1.1 발단 및 전개

     

    로그아웃 기능 코드를 구현하고 테스트를 하는 과정에서 에러가 발생했다. 

     

    except InvalidToken 으로 예외처리를 해줬는데 왜그럴까? 🤔

     

     

     

     or 로 발견된 예외코드를 추가해줬다. 

    except InvalidToken or TokenError:

     

     

     

    1. 2 위기 및 해결

     

    수정 후 다시 테스트를 했는데 여전히 에러가 났다.

    할 수 없이 구글링 하다, gpt에 물어보니 이런 경우에는 튜플로 처리를 해줘야 한다고 한다.

     

     

    다시 테스트 해본 결과 잘 해결되었다. 

     

     

     

    하지만 간결하게 코드를 작성하고 싶어서 또다시 구글링 하다보니 TokenError가 InvalidToken을 포함하는 범용적인 에러이기 때문에 TokenError만을 사용하여 예외를 처리하는 것이 좋다고 한다. 정말 그런지 튜터님께 여쭤봐야겠다.

     

    그래서 아래와 같이 코드를 정리했다.

    from rest_framework.permissions import IsAuthenticated
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework_simplejwt.tokens import RefreshToken, TokenError
    from rest_framework import status
    
    class SignoutView(APIView):
        permission_classes = [IsAuthenticated]
    
        def post(self, request):
            refresh_token_str = request.data.get("refresh_token")
    
            # 토큰이 제공되지 않았을 때 
            if not refresh_token_str:
                return Response({"error": "토큰이 제공되지 않았습니다."}, status=status.HTTP_400_BAD_REQUEST)
    
            try:
                # RefreshToken 생성
                refresh_token = RefreshToken(refresh_token_str)
    
                # 블랙리스트에 추가
                refresh_token.blacklist()
                return Response({"message": "로그아웃되었습니다."}, status=status.HTTP_200_OK)
    
            except TokenError:
                # 유효하지 않은 토큰
                return Response({"error": "유효하지 않은 토큰입니다."}, status=status.HTTP_400_BAD_REQUEST)

     

     


     

     

    2.1 발단 및 전개

     

    회원가입 시, 처음 성별 필드에 조건에 아무것도 주지 않았다. max_length=10로 최대 글자수, blank=True null=True 로 빈 값으로 둘 수 있게만 해두었다.

     

    구현할 때 조건이 성별과 자기소개는 생략 가능이었기 때문이이다. 하지만 아래 코드를 보면, 유저는 입력을 안 할 수는 있지만 홈런볼이나 콩떡 같은 아무 키워드나 입력할 수도 있다. 

     

      

    그래서 다시, 유저가 성별을 선택할 수 있도록 GENDER_CHOICES 를 추가했다.

     

    근데 Error가 떴다 🧐

     

     

    2.2 위기 및 해결

     

     

    NameError: name 'GENDER_CHOICES' is not defined 에러는 GENDER_CHOICES가 gender 필드가 정의된 시점보다 먼저 정의되지 않았기 때문에 생긴 문제였다.

     

     

    그래서 이렇게 수정해주었다.

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    class CustomUser(AbstractUser):
    
        GENDER_CHOICES = (
            ('male', '남성'), 
            ('female', '여성'),
        )
    
        name = models.CharField(max_length=30, default='default_name', null=False, blank=False)
        nickname = models.CharField(max_length=20, unique=True)
        email = models.EmailField(unique=True)
        birth = models.DateField(null=False, blank=False)  
        gender = models.CharField(max_length=10, choices=GENDER_CHOICES, blank=True, null=True)
        introduction = models.TextField(blank=True, null=True)

     

     

     

    서버 켜보면 잘 요청되고 잘 응답한다👌

     


     

    3.1 배경 및 발단

     

    근데 회원가입  했을 때 해싱된 비밀번호가 보이면 안되지 않나.. 근데 내 포스트맨은.. 테스트 해보니 Respond에 이렇게 유저 비밀번호가 보인다.. 🤔

     

    이게 내 원래 코드

     

     

    password 같은 필드 값은 서버에는 전송되지만 응답을 돌려줄 때는 반환되지 않아야 한다. 즉, 쓰기전용 기능을 하는 아이 ↓

    write_only=True

     

     

    수정한 코드↓ 한 줄만 추가해주면 된다!

     

     

    3.2 전개 

    서버를 키고, Postman에서 테스트를 해보면? 응? 😟 

     

    TypeError? 

     

    타입에러가 생기면 서버 실행조차 안된다😥

     

     

    3.3 해결

     

    오타였다.. write을 wrtite로 써서 생긴 오타...

     

     

    자 이제 서버 실행하고 테스트 해보면 잘 된다👌

     

    위에는 요청에는 Bodypassword가 있지만 응답에는 password 정보를 받고있지 않다.

     

     

    수정된 코드

    from rest_framework import serializers
    from .models import CustomUser
    
    class UserSerializer(serializers.ModelSerializer):
    
        password = serializers.CharField(write_only=True)
    
        class Meta:
            model = CustomUser
            fields = ['username', 'name', 'nickname', 'email', 'birth', 'password', 'gender', 'introduction']
    
        def create(self, validated_data):
            user = CustomUser(**validated_data)
            user.set_password(validated_data['password'])
            user.save()
            return user
    
    class UserProfileSerializer(serializers.ModelSerializer):
        class Meta:
            model = CustomUser
            fields = ['username', 'nickname', 'email', 'birth', 'introduction']

     

     

    처음부터 코드를 잘 구현해야 하겠지만, 테스트하면서 이상한 점을 발견하고 계속해서 코드를 수정보완 할 수 있어서 다행이라는 생각이 들었다. 그러다 코드가 산으로가도 온전히 내 책임이긴 하지만.. 또 나뿐만 아니라 오타로 인한 에러가 생각보다 꽤 많은 것 같다. 그리고 그러한 에러는 내가 오타를 썼을거라고는 전혀 생각하지 않고 있기 때문에 해결하는데 꽤나 오랜 시간이 걸린다🤔

     

    트러블 슈팅은 정말 중요한 과정인데 해결을 했다는데만 기뻐서 대충 적어놓고는 넘어가버렸다. 그러고나니 막상 적으려고 할 땐 기억이 잘 나지 않는다. 지금도 몇 개가 더 있었는데.. 캡처도 해논 것 같은데 도저히 못찾겠다..ㅠㅠ 

    다음부턴 문제의 발단과 해결 과정을 그때 그때 꼼꼼하게 기록해 놓아야겠다..ㅠㅠ

     

     

     

Designed by Tistory.