Writable Nested Serializer로 중첩된 객체 한 번에 생성/수정하기
DRF의 기본 ModelSerializer는 중첩된 관계에 대해 읽기 전용으로 동작하는데, create()와 update() 메서드를 오버라이드하여 단일 API 호출로 부모-자식 객체를 원자적으로 생성/수정하는 방법
문제 상황과 해결책
기존 비효율적인 방식
게시글 생성 후 태그를 별도로 연결하는 다중 API 호출
네트워크 오버헤드와 데이터 정합성 문제 발생
해결책
단일 API 호출로 중첩된 객체들을 한 번에 처리
클라이언트 로직 단순화와 성능 향상
구현 원리
핵심 메커니즘
부모 Serializer의
create()와update()메서드 오버라이드validated_data.pop()으로 중첩 데이터 분리부모 객체 생성 후 자식 객체들과 관계 설정
1:N 관계 구현 (ForeignKey)
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True)
@transaction.atomic
def create(self, validated_data):
tracks_data = validated_data.pop('tracks')
album = Album.objects.create(**validated_data)
for track_data in tracks_data:
Track.objects.create(album=album, **track_data)
return albumM:N 관계 구현 (ManyToMany)
class PostSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True)
@transaction.atomic
def create(self, validated_data):
tags_data = validated_data.pop('tags')
post = Post.objects.create(**validated_data)
tag_list = []
for tag_data in tags_data:
tag, created = Tag.objects.get_or_create(name=tag_data['name'])
tag_list.append(tag)
post.tags.set(tag_list)
return post실무 핵심 팁
필수 사항
@transaction.atomic데코레이터로 데이터 정합성 보장get_or_create활용으로 중복 데이터 방지ViewSet에서
prefetch_related사용으로 N+1 쿼리 문제 방지
복잡도 관리
로직이 복잡해지면 서비스 계층 분리 고려
과도한 중첩보다는 별도 엔드포인트 제공도 고려
성능 최적화
bulk_create활용으로 대량 데이터 처리 최적화필요한 데이터를 미리 한 번의 쿼리로 조회
Last updated
