아마 이 글을 읽고 계신다면, Django 개발 중 N+1 문제를 겪고 계시거나, 예전에 한 번이라도 마주친 경험이 있으실 겁니다. 이 문제 때문에 페이지 로딩 속도가 느려지고, 해결 방법을 찾다가 select_related
와 prefetch_related
를 알게 되었을 가능성이 높습니다.
우선, 제 블로그에 잘 찾아오셨습니다! 🎉 이 글을 끝까지 읽으면, N+1 문제를 효과적으로 해결하는 방법을 확실히 익히실 수 있습니다.
혹시 아직 N+1 문제의 개념을 정확히 모르신다면, 먼저 아래 글을 읽어보시는 것을 추천드립니다.
✅ Django ORM에서 N+1 문제란? 왜 발생할까?
🔍 Django에서 N+1 문제를 해결하는 두 가지 방법
Django ORM에서는 select_related
와 prefetch_related
두 가지 기능을 제공하여 N+1 문제를 해결할 수 있습니다. 하지만 두 기능이 동작하는 방식이 다르므로, 어떤 경우에 각각을 사용해야 하는지 정확히 이해하는 것이 중요합니다.
📌 select_related
와 prefetch_related
의 공통 원리
이 두 메서드의 핵심 공통 원리는 로직을 위해 필요한 필드를 첫 쿼리에서 한꺼번에 DB에서 가져와서, Django 내부에서 가져온 데이터를 효율적으로 활용한다는 점입니다.
예를 들어, 케이크를 만들기 위해 대형 슈퍼마켓에 가서 밀가루, 휘핑크림, 과일 등 필요한 재료를 한 번에 다 사가지고 온다고 생각해보세요. 집에 돌아와서 요리를 시작하면, 모든 재료가 한꺼번에 준비되어 있으니 바로 조리가 가능합니다.
하지만 만약 필요한 재료를 하나씩 따로 사러 간다면 어떨까요? 밀가루를 사고 돌아와서 반죽을 시작하려고 보니 휘핑크림이 없어서 다시 슈퍼에 가야 하고, 휘핑크림을 사 와서 작업하려는데 이번엔 과일이 없어서 또 마트를 가야 한다면?
이런 방식으로는 요리가 굉장히 오래 걸릴 것입니다. Django ORM에서 select_related
와 prefetch_related
는 이런 비효율적인 데이터 호출을 방지하고, 한 번의 데이터베이스 쿼리로 필요한 데이터를 미리 가져와서 빠르게 처리할 수 있도록 도와주는 역할을 합니다.
✅ 1. select_related
– SQL JOIN을 활용한 즉시 로딩
ForeignKey(1:N) 관계에서 사용
- SQL JOIN을 사용하여 한 번의 쿼리로 데이터를 가져옴
- 즉시 관련 객체를 가져오기 때문에 추가적인 데이터베이스 요청이 없음
📌 select_related
사용 예제
authors = Author.objects.select_related('post_set').all()
🧐 select_related
가 적용되지 않았을 때 실행되는 SQL
SELECT * FROM author;
SELECT * FROM post WHERE author_id = 1;
SELECT * FROM post WHERE author_id = 2;
...
🚀 select_related
를 적용했을 때 실행되는 SQL
SELECT * FROM author INNER JOIN post ON author.id = post.author_id;
✅ 2. prefetch_related
– 개별 쿼리를 활용한 미리 로딩
ManyToMany, Reverse ForeignKey 관계에서 사용
- 개별적인 쿼리를 실행한 후, Django가 Python에서 데이터를 최적화하여 연결
- SQL JOIN을 사용하지 않으므로, 대량의 데이터를 처리할 때 더 유리할 수도 있음
📌 prefetch_related
사용 예제
authors = Author.objects.prefetch_related('post_set').all()
🧐 prefetch_related
적용 후 실행되는 SQL
SELECT * FROM author;
SELECT * FROM post WHERE author_id IN (1, 2, 3, 4, 5, ...);
🎯 마무리 – 이렇게만 하면 N+1 문제 해결!
Django ORM을 사용할 때 N+1 문제를 방치하면 성능이 심각하게 저하될 수 있습니다. 하지만 select_related
와 prefetch_related
를 적절히 사용하면 SQL 실행 횟수를 최소화하고, 페이지 로딩 속도를 대폭 개선할 수 있습니다.
✅ 정리
- ForeignKey(1:N) 관계라면
select_related
사용 - ManyToMany 또는 역참조 관계라면
prefetch_related
사용 - 어떤 경우든 실행되는 SQL을 확인하며 최적화 필요
- 쿼리 실행 속도가 느려진다면, N+1 문제를 의심해야 함
📌 관련 글도 함께 읽어보세요!
✅ Django ORM에서 N+1 문제란? 왜 발생할까?
이제 select_related
와 prefetch_related
를 활용해서 N+1 문제를 해결해보세요! 🚀 혹시 이해가 잘 안 되거나, 추가적인 궁금증이 있다면 댓글이나 질문을 남겨주세요. 😊
Add a New Comment