select_related, prefetch_related 실전 패턴과 실수 피하기

Django ORM에서 N+1 쿼리 문제를 해결하는 핵심 메서드인 select_related와 prefetch_related의 사용법과 실전 패턴을 다룸. 각각의 적절한 사용 시점과 흔한 실수를 방지하는 방법 제시

N+1 쿼리 문제

  • ORM 사용 시 가장 흔한 성능 병목점

  • 초기 쿼리 1번 + 반복문에서 N번의 추가 쿼리 발생

  • 데이터가 많아질수록 응답 시간 기하급수적 증가

  • ForeignKey와 OneToOneField의 정방향 관계에서 사용

  • SQL JOIN을 사용하여 관련 객체를 단일 쿼리로 조회

  • 관계된 객체가 1개일 때 효율적

  • 여러 단계 중첩 관계도 __로 연결하여 한 번에 처리 가능

  • ManyToManyField와 ForeignKey 역방향 참조에서 사용

  • 별도 쿼리 실행 후 파이썬 레벨에서 데이터 조합

  • JOIN으로 인한 데이터 중복 방지

  • 최소 2개 이상의 쿼리 실행 (원본 + 관계별 쿼리)

핵심 선택 기준

관계 유형
사용 메서드

ForeignKey (정방향)

select_related

OneToOneField

select_related

ManyToManyField

prefetch_related

ForeignKey (역방향)

prefetch_related

실전 패턴

두 메서드 함께 사용

  • ForeignKey는 select_related, ManyToManyField는 prefetch_related 동시 적용

Prefetch 객체 활용

  • 커스텀 쿼리셋으로 DB 레벨에서 필터링

  • to_attr로 결과를 별도 속성에 저장

주요 실수 및 주의사항

잘못된 메서드 선택

  • ManyToManyField에 select_related 사용 시 효과 없음

  • ForeignKey에 prefetch_related 사용 시 비효율적

Serializer와 Model Property의 숨은 N+1

  • SerializerMethodField와 source 옵션 사용 시 주의

  • Model의 @property에서 관계 접근 시 최적화 필요

  • prefetch 이후 filter 사용 시 캐시 무효화 가능

  • 필터링을 prefetch 이전에 실행

Last updated