기술블로그-Django편
📌 Django에서 prefetch_related 완전 정복하기 (쿼리 최소화)
Chansman
2025. 5. 9. 17:10
📌 Django에서 prefetch_related 완전 정복하기
✅ 시작 질문: 이 코드 도대체 왜 쓰는 거야?
queryset = Blog.objects.all().prefetch_related('comment_set', 'comment_set__author')
사용자가 궁금했던 핵심:
이 코드는 뭔가 복잡한 것 같은데, 꼭 써야 해요?
왜 prefetch_related()를 쓰는 건지, 실질적으로 어떤 차이가 나는지 모르겠어요.
1️⃣ prefetch_related란?
Django ORM에서 prefetch_related()는 N+1 쿼리 문제를 막기 위한 최적화 도구입니다.
🔍 N+1 문제란?
- 블로그 10개를 불러온 후, 각 블로그의 댓글을 따로따로 불러오면:
→ 총 1 + 10 = 11번의 쿼리가 날아감 - 거기에 댓글 작성자까지 불러오면?
→ 댓글 수만큼 추가 쿼리 발생 → 수십~수백 개 쿼리 😱
2️⃣ prefetch_related 사용 시 쿼리 흐름
queryset = Blog.objects.all().prefetch_related('comment_set', 'comment_set__author')
- 1번 쿼리: Blog 전체 가져오기
- 2번 쿼리: 모든 블로그의 댓글(comment_set) 가져오기
- 3번 쿼리: 모든 댓글의 작성자(author) 가져오기
✅ 총 3번의 쿼리로 끝남 → 훨씬 효율적!
3️⃣ 코드 설명 하나씩 뜯어보기
Blog.objects.all()
→ 블로그 전체 조회
.prefetch_related('comment_set')
→ 블로그별로 연결된 댓글을 미리 한 번에 가져오기
.prefetch_related('comment_set__author')
→ 각 댓글마다 연결된 작성자(author)도 같이 가져오기
💡 이렇게 하면 템플릿이나 뷰에서 접근할 때 추가 쿼리가 발생하지 않음!
✅ 예시 흐름 비교
❌ prefetch_related 안 쓴 경우
for blog in Blog.objects.all():
for comment in blog.comment_set.all():
print(comment.author.username)
→ 블로그 10개 + 댓글 50개 → 수십 번 쿼리 발생 ⚠️
✅ prefetch_related 쓴 경우
for blog in Blog.objects.all().prefetch_related('comment_set', 'comment_set__author'):
for comment in blog.comment_set.all():
print(comment.author.username)
→ 쿼리 3번으로 끝! ⚡
📌 결론 요약
항목 내용
목적 | 연관된 객체(댓글, 작성자)를 미리 가져와서 DB 효율 향상 |
결과 | 쿼리 수 감소, 성능 개선, 속도 향상 |
언제 사용? | ForeignKey, OneToMany 관계에서 .all(), .filter() 등 루프 돌릴 때 |
💬 한 줄 정리
prefetch_related()는 "미리 다 끌어와서 캐시해두고, 쿼리 최소화하는 비밀 병기"입니다 💪