Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

Nonamed Develog

[TIL][240904] Troubleshooting 1: validaors.py의 활용 본문

WHAT I LEARN/TIL

[TIL][240904] Troubleshooting 1: validaors.py의 활용

노네임드개발자 2024. 9. 4. 22:03

문제 상황

Django REST Framework를 이용해 사용자 회원가입, 로그인, 로그아웃, 프로필 관리 등을 구현하는 과정에서, 검증 로직이 각 뷰에 산재해 있어 중복된 코드가 많았고 유지보수가 어렵다는 문제를 겪었다. 또한, 비밀번호 확인과 같은 검증 로직이 일부 누락되어 있어 보완할 필요가 있었다. 특히, 회원가입 시 비밀번호 확인이메일 중복 검사가 간단한 수준에서 처리되었고, 수정 시 이를 반복적으로 작성해야 했다.

문제 원인

  • 유효성 검증이 분산되어 관리: 회원가입, 로그인, 프로필 수정 등에서 유효성 검증 로직이 뷰에 직접 구현되어 있어 중복된 코드가 많았고, 검증 기준이 다를 수 있는 문제점이 발생했다.
  • 비밀번호 및 이메일 검증 누락: 회원가입 시 비밀번호 일치 여부를 확인하는 부분이 없었고, 이메일 형식과 중복 검사가 제한적이었다.

초기 코드

초기에는 모든 검증 로직이 뷰나 시리얼라이저에 흩어져 있었다.

class NewAccountSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True)

    class Meta:
        model = User
        fields = ['username', 'password', 'email', 'name', 'nickname', 'date_of_birth', 'gender', 'bio']
        
    def create(self, validated_data):
        user = User.objects.create_user(
            username=validated_data['username'],
            password=validated_data['password'],
            email=validated_data['email'],
            name=validated_data.get('name', ''),
            nickname=validated_data.get('nickname', ''),
            date_of_birth=validated_data.get('date_of_birth'),
            gender=validated_data.get('gender', ''),
            bio=validated_data.get('bio', '')
        )
        return user

 

문제 분석

  • 중복된 검증 로직: 회원가입뿐만 아니라 로그인, 계정 삭제 등 여러 뷰에서 비슷한 검증 로직이 사용되고 있었고, 이를 효율적으로 재사용할 필요가 있었다.
  • 비밀번호 검증 부재: 기존 회원가입에서는 비밀번호와 비밀번호 확인을 비교하는 과정이 빠져 있어, 비밀번호 불일치로 인한 오류 처리가 미비했다.
  • 이메일 중복 검증의 미흡함: 이메일 형식 검증과 중복 검사가 제대로 이루어지지 않아, 잘못된 이메일이나 중복된 이메일로 회원가입이 이루어질 가능성이 있었다.

해결 방법

validators.py 파일을 만들어 유효성 검증 로직을 중앙 집중화하고, 회원가입, 프로필 수정, 비밀번호 변경 등에서 이를 재사용하도록 코드를 리팩토링하였다.

from django.core.exceptions import ValidationError
from django.core.validators import validate_email as django_validate_email
from django.contrib.auth.hashers import check_password
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.exceptions import TokenError

# 회원가입 검증
def validate_user_data(signup_data):
    err_msg_dict = {}
    username = signup_data.get('username')
    email = signup_data.get('email')
    password = signup_data.get('password')
    password_check = signup_data.get('password_check')

    # 사용자명 중복 확인
    if User.objects.filter(username=username).exists():
        err_msg_dict['username'] = "이미 존재하는 사용자명입니다."
    
    # 비밀번호 일치 여부 확인
    if password != password_check:
        err_msg_dict['password'] = "비밀번호가 일치하지 않습니다."

    # 이메일 형식 및 중복 확인
    try:
        django_validate_email(email)
    except ValidationError:
        err_msg_dict['email'] = "유효하지 않은 이메일 형식입니다."

    if User.objects.filter(email=email).exists():
        err_msg_dict['email'] = "이미 사용 중인 이메일입니다."

    if not err_msg_dict:
        return True, None
    return False, err_msg_dict

 

이 코드를 통해 회원가입 시에 필요한 다양한 유효성 검증이 하나의 함수로 처리되며, 뷰와 직렬화에서 코드가 간결해졌다.

변경된 뷰 코드

class NewAccountAPIView(APIView):
    def post(self, request):
        # validators.py를 통한 유효성 검증 호출
        is_valid, error_message = validate_user_data(request.data)
        if not is_valid:
            return Response({"error": error_message}, status=status.HTTP_400_BAD_REQUEST)

        serializer = NewAccountSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

 

추가된 검증 기능

  • 비밀번호 검증: 비밀번호와 비밀번호 확인을 일치하도록 검증하는 로직이 추가되었다.
  • 이메일 중복 및 형식 검증: 이메일의 형식을 확인하고, 중복되는 이메일이 있을 경우 에러 메시지를 반환한다.

결과

  • 중앙 집중화된 유효성 검사: 검증 로직이 validators.py에 모여 있어 코드 재사용성이 높아졌고, 관리가 훨씬 수월해졌다.
  • 코드 간소화: 뷰와 직렬화에서의 검증 로직이 사라지면서 코드가 깔끔해졌고, 유지보수가 쉬워졌다.
  • 에러 처리 개선: 회원가입 시 비밀번호 불일치나 이메일 중복 등의 에러를 세밀하게 처리할 수 있게 되었다.

배운 점

  • 유효성 검증 로직의 분리: 뷰와 직렬화에서 검증 로직을 분리해 validators.py로 집중화함으로써, 코드 중복을 줄이고, 효율적인 에러 처리가 가능해졌다.
  • 더 나은 유지보수: 검증 로직을 한곳에 모아두면 코드 변경 시에도 유지보수가 쉬워지고, 필요한 부분만 수정하면 전체 로직에 영향을 줄 수 있어 더욱 효율적이다.

이 과정을 통해 유효성 검증 로직을 개선하고, 더 깔끔한 코드 구조를 갖출 수 있었습니다.