Django REST Framework에서 Serializer 중첩 처리하기
문제 상황
사용자 목록 API에서 각 사용자의 프로필 정보를 함께 반환해야 했다. 처음에는 단순하게 Serializer를 중첩해서 구현했다.
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ['bio', 'avatar_url']
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer(read_only=True)
class Meta:
model = User
fields = ['id', 'username', 'email', 'profile']
기능은 정상 작동했지만, 사용자가 100명이면 쿼리가 101번 실행되는 전형적인 N+1 문제가 발생했다.
해결 방법
ViewSet에서 select_related를 사용해 쿼리를 최적화했다.
class UserViewSet(viewsets.ModelViewSet):
serializer_class = UserSerializer
def get_queryset(self):
return User.objects.select_related('profile').all()
이렇게 수정하니 쿼리가 1번으로 줄어들었다. Django ORM의 select_related는 SQL JOIN을 사용해 관련 객체를 미리 가져온다.
추가 고려사항
- ManyToMany나 역참조 관계는
prefetch_related사용 - 중첩 깊이가 깊어지면 응답 크기가 커지므로 필요한 필드만 선택
- 쓰기 작업 시에는 중첩된 Serializer의
create/update메서드 오버라이드 필요
Django Debug Toolbar를 사용하면 실제 실행되는 쿼리를 쉽게 확인할 수 있어서 성능 최적화에 유용했다.