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

목차
DRF API 응답 구조 변경
무슨 글을 쓸까 고민하다가 오름캠프에서 학생들에게 질문 받았던 것 중에서 하나 골라봤습니다.
ModelSerializer
를 상속 받아서 API를 구현하는데 사용했는데 응답 구조를 어떻게 변경하나요?
클라이언트와 데이터를 주고 받을 때 Serializer
를 통하게 되고 Model
에 정의된 데이터를 사용하려면 ModelSerializer
를 사용해서 쉽게 직렬화할 수 있습니다. 거기에 추가적인 데이터를 응답에 포함하거나 구조를 변경해야 할 때도 있습니다. 상황에 따라 다양한 방법을 써볼 수 있겠습니다만 이번 포스팅에서 SerializerMethodField
와 to_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 메소드 오버라이딩
Serializer
에 to_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
을 쓰면 될 것 같습니다.