(본 글은 Nomadcoders 커뮤니티에 한 번 올렸던 글을 여기에 옮겨 올리는 것입니다.)
Django에서 정참조 multiple objects(many-to-many or one-to-many)이거나, 또는 역참조 Foreign Key일때 사용하는 것이 prefetch_related입니다.
에어비앤비 강의를 예를 들면 amenity와 rooms가 many-to-many이고 예약과 리뷰가 one-to-many라 볼 수 있습니다.(review에서 reservations를 foreign key를 가짐)
Instagram이나 Youtube 등 보통의 SNS를 떠올리면 알 수 있듯이 Comment가 Post(게시물)에 종속되기 때문에 제 Westa Clone에서도 Comment가 Foreign Key로 post 필드를 가지며 post가 Comment를 역참조한다고 볼 수 있습니다.
Post 모델과 Comment 모델만 가지고 간단하게 쿼리를 하나씩만 가져와 보겠습니다.
id가 1인 포스트를 필터링 해서 첫번째 아이템을 지정해서 post에 넣을 때 한 번의 쿼리가 실행되고 Post.comment_set.all()에서 쿼리가 또 실행됩니다. 이 때 post에 코멘트가 10개가 있다고 치면 for에서 그걸 돌려서 comment 하나씩에 대해 처리를 한다고 하면 query가 10번 돌게 됩니다.
그에 반해, 보라색 줄 친 prefetch_related를 이용해 comment_set을 포함해 가져오는 경우에는 id가 1인 포스트에 달린(?) 코멘트들을 모조리 오브젝트에 함께 가져오도록 Python 상에서 쿼리를 처음부터 작성하여 실행하게 됩니다. 그러므로 post_pr에서 이미 쿼리 조작은 끝납니다.
그 다음엔 위에 파란줄의 (2)처럼 post_pr.comments.all()을 하더라도 쿼리를 다시 가져오는 게 아닌 오브젝트 내에 있는 다시 말하면 cache 되어 있는 오브젝트를 가져와서 처리를 하게 됩니다.
이 역시 쿼리를 적게 실행한다는 점에서 서버와의 통신 회수를 줄일 수 있으니 앱의 효율화에 기여할 수 있다고 볼 수 있습니다.(라고 합니다.)
끝.