[4th TeamProject] - 회원가입 뷰 & 회원 시리얼라이저

장현웅·2023년 10월 20일
1

처음 DRF를 배울 때, 프로젝트를 시작하고 처음 기능 구현을 시작하는 것은 보통 회원가입 기능이었습니다. 이 때, 처음 접하는 클래스 뷰(CBV, Class Based View)와 시리얼라이저도 낯설었지만 그 정도는 일단 먼저 구현해보고 분석해도 충분하다고 생각했습니다. 하지만 회원가입부터 도저히 이해가 안가는 부분이 있었어서 그 부분에 대해서 정리해보려고 합니다.

  • [ 뷰 ]
1    class RegisterView(APIView):
2        def post(self, request):
3            """사용자 정보를 받아 회원가입 합니다."""
4            serializer = UserSerializer(data=request.data, context={'profile_img':request.FILES})
5            if serializer.is_valid():
6                serializer.save()
7                return Response({'message':'회원가입 성공'}, status=status.HTTP_201_CREATED)
8            else:
9                return Response({'message': serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
  • [ 시리얼라이저 ]
1    class UserSerializer(serializers.ModelSerializer):
2        """회원가입 페이지, 회원 정보 수정 페이지에서 사용되는 시리얼라이저입니다."""
3        class Meta:
4            model = User
5            fields = "__all__"
6
7        def create(self, validated_data):
8            user = super().create(validated_data)
9            password = user.password
10            user.set_password(password)
11            user.save()
12
13            profile_img = self.context['profile_img']
14            # print(profile_img)
15
16            for image_data in profile_img.getlist('profile_img'):
17                # print(image_data)
18                ProfileImage.objects.create(owner=user, profile_img=image_data)
19            return user

여기서 도저히 이해가 안가던 부분은 '[ 뷰 ]의 6번 row의 .save()'와 '[ 시리얼라이저 ]의 11번 row의 .save()'이 두 부분이었습니다. '왜 저장을 두 번이나 하지..?' 알아본 바로는 [ 뷰 ]에서 사용자가 보낸 데이터를 넣은 시리얼라이저의 유효성 검사를 하고 '.save()' 메서드가 발동되면 [ 시리얼라이저 ]의 'create'메서드와 'update'메서드가 둘 다 호출 되는데 'instance'의 유무에 따라 둘 중 한 메서드가 발동됩니다.

'.save()'메서드를 'ctrl+click'으로 들어가보면 'create'메서드와 'update'메서드를 확인할 수 있습니다. 우리는 이 함수들을 오버라이드하여 재정의한 메서드를 사용하는 것입니다.

def update(self, instance, validated_data):
    raise NotImplementedError('`update()` must be implemented.')

def create(self, validated_data):
    raise NotImplementedError('`create()` must be implemented.')

실제로 데이터베이스에 모델 객체를 저장하는 것은 [ 시리얼라이저 ]의 '.save()'부분에서 담당합니다.

추가적으로, [ 시리얼라이저 ] 내의 'super().create(validated_data)'부분의 'create' 메서드로 새 사용자 객체를 생성할 때, 기본적으로 모델을 생성하고 데이터베이스에 저장합니다. 저는 이게 비효율적이라고 생각하여 아래와 같이 코드를 짰습니다.

from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    """회원가입 페이지, 회원 정보 수정 페이지에서 사용되는 시리얼라이저입니다."""

    class Meta:
        model = User
        fields = "__all__"

    def create(self, validated_data):
        # 사용자 모델을 직접 생성
        user = User(**validated_data)
        
        # 비밀번호 설정
        password = user.password
        user.set_password(password)

        # 데이터베이스에 저장
        user.save()

        profile_img = self.context.get('profile_img')

        if profile_img:
            for image_data in profile_img.getlist('profile_img'):
                ProfileImage.objects.create(owner=user, profile_img=image_data)

        return user

위 코드에서 'User(validated_data)'를 사용하여 사용자 모델을 생성하고, 'user.save()'를 호출하여 데이터베이스에 저장합니다. 이렇게 하면 'super().create(validated_data)'를 사용하지 않고 원하는 대로 동작하며, 중복 저장 문제도 해결됩니다.

1개의 댓글

comment-user-thumbnail
2023년 10월 23일

놓친 부분을 파악하고 코드를 고쳐 문제를 해결하는 점이 기록되어 있어 좋네요!

답글 달기