DRF Serializer에서 API 응답 구조 변경(feat.to_representation, SerializerMethodField)

프로필 사진mingke

DRF Serializer에서 API 응답 구조 변경(feat.to_representation, SerializerMethodField)

목차

DRF API 응답 구조 변경

무슨 글을 쓸까 고민하다가 오름캠프에서 학생들에게 질문 받았던 것 중에서 하나 골라봤습니다.

💡

ModelSerializer를 상속 받아서 API를 구현하는데 사용했는데 응답 구조를 어떻게 변경하나요?

클라이언트와 데이터를 주고 받을 때 Serializer 를 통하게 되고 Model 에 정의된 데이터를 사용하려면 ModelSerializer 를 사용해서 쉽게 직렬화할 수 있습니다. 거기에 추가적인 데이터를 응답에 포함하거나 구조를 변경해야 할 때도 있습니다. 상황에 따라 다양한 방법을 써볼 수 있겠습니다만 이번 포스팅에서 SerializerMethodFieldto_representation 메소드를 이용한 방법을 알아보겠습니다.

예시 코드

임의로 다음과 같은 예시를 만들었습니다.

class Post(models.Model):
    user = models.ForeignKey("accounts.User", on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    content = models.TextField()
    like = models.ManyToManyField(User, blank=True)
 
class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['id', 'user', 'title', 'content']

SerializerMethodField

SerializerMethodField 는 DRF에서 제공하는 특별한 필드라고 할 수 있습니다. 모델에 존재하지 않는 데이터를 동적으로 생성해서 응답에 포함시킬 수 있습니다. 기본적으로 read_only이고 get_<field_name> 메소드를 정의해서 사용할 수 있습니다.

위 예시에서 만약 좋아요 개수를 응답에 추가하고 싶다면 다음과 같이 해볼 수 있습니다.

class PostSerializer(serializers.ModelSerializer):
    like_count = serializers.SerializerMethodField()
 
    class Meta:
        model = Post
        fields = ['id', 'user', 'title', 'content', 'like_count']
 
    def get_like_count(self, obj):
        return obj.like.count()

like_count를 SerializerMethodField 로 선언하고 get_like_count 메소드를 정의하여 사용하면 좋아요 개수가 응답에 추가됩니다.

to_representation 메소드 오버라이딩

Serializerto_representation 이라는 메소드가 있습니다. representation의 뜻은 표현입니다. to_representation 메소드는 응답을 어떻게 표현하는가에 관련된 메소드라고 생각하면 좋을 것 같습니다. to_representation더 많은 응답 필드를 변경하는 경우에 사용하는 것이 더 적합하다고 할 수 있습니다.

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['id', 'user', 'title', 'content']
 
    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['like_count'] = instance.like.count()
        data['user'] = {
            "id": instance.user.id,
            "username": instance.user.username,
            "email": instance.user.email
        }
        data['is_popular'] = instance.like.count() > 100
        return data

to_representation을 이용해서 user 정보도 추가하고 is_popular 필드도 추가했습니다. 여러 개의 응답 필드를 조작해 볼 수 있습니다. user 데이터 같은 경우는 user를 위한 Serializer를 만들어서 Nested Serializer로 사용하는게 더 좋습니다.

마무리

간단한 예시로 API응답을 변경하는 방법을 알아봤습니다. 상황에 따라 구현하는 방법이 달라 질 것인데 상황에 맞게 사용하면 되겠습니다. 단순히 간단한 필드는 1~2개 추하면 SerializerMethodField 를 쓰고 응답 구조를 많이 변경하면 to_representation 을 쓰면 될 것 같습니다.

Loading...