Django로 개발하다 보면 '지연 평가(Lazy Evaluation)'라는 용어를 자주 접하게 됩니다.
하지만 이 개념이 정확히 무엇인지, Django에서 어떻게 동작하는지 궁금했던 분들도 많을 텐데요.
이번 글에서는 '지연 평가'가 무엇인지, Django ORM에서 어떻게 활용되는지 살펴보겠습니다.
1️⃣ 지연 평가(Lazy Evaluation)란?
"필요할 때까지 DB에서 데이터를 가져오지 않는다!"
Django의 QuerySet은 기본적으로 Lazy Evaluation(지연 평가)를 따릅니다.
즉, QuerySet을 만들더라도 실제로 데이터를 요청하기 전까지 쿼리가 실행되지 않습니다.
✅ 예제: Lazy Evaluation
from myapp.models import Post
# QuerySet을 생성 (아직 DB에서 데이터를 가져오지 않음)
post_list = Post.objects.filter(status='PB')
print(post_list)
# <QuerySet [ ]># ✅ 아직 DB에 쿼리를 실행하지 않음
# 🔥 실제로 데이터를 조회할 때 DB 쿼리가 실행됨
for post in post_list:
print(post.title) # 🚀 여기서 DB 쿼리 발생
- post_list는 QuerySet 객체지만, 아직 DB에 접근하지 않음
- 하지만 데이터를 사용할 때 실제로 쿼리가 실행됨
✅ 이것이 바로 "Lazy Evaluation" (지연 평가)!
2️⃣ 즉시 평가(Eager Evaluation)란?
"데이터를 즉시 가져와서 리스트나 변수로 변환한다!"
지연 평가를 깨고 QuerySet을 즉시 실행하려면, 즉시 평가(Eager Evaluation)를 사용하면 됩니다.
✅ 예제: 즉시 평가
post_list = list(Post.objects.filter(status='PB')) # ✅ 즉시 DB 쿼리 실행됨 print(post_list) #
[<Post: Post 1>, <Post: Post 2>] # 🚀 QuerySet이 아니라 실제 객체 리스트가 반환됨!
📌 즉시 평가를 적용하면:
- QuerySet이 리스트로 변환되면서 즉시 데이터를 가져옴
- 더 이상 Django ORM 기능 (
.filter()
,.annotate()
)을 사용할 수 없음
3️⃣ `.values()`와 `.values_list()`의 즉시 평가
.values()
와 .values_list()
도 기본적으로 Lazy Evaluation을 유지하지만,
이를 list()
로 감싸면 즉시 평가가 적용됩니다.
✅ Lazy Evaluation 유지 (지연 평가)
post_list = Post.objects.filter(status='PB').values("id", "title")
print(post_list)
# <QuerySet [{'id': 1, 'title': 'First Post'}, {'id': 2, 'title': 'Second Post'}]> # QuerySet 객체
🚨 이 상태에서는 여전히 QuerySet이므로, 데이터를 사용할 때마다 평가됩니다. 🔥 즉시 평가 적용
post_list = list(Post.objects.filter(status='PB').values("id", "title"))
print(post_list)
# [{'id': 1, 'title': 'First Post'}, {'id': 2, 'title': 'Second Post'}] # 🚀 즉시 평가됨 (리스트로 변환)
✅ 이제 QuerySet이 아니라 리스트가 되었고, Django ORM 기능 (.filter()
, .annotate()
)을 사용할 수 없습니다. ✅ 하지만 데이터를 미리 가져왔으므로, 이후 DB 접근 없이 빠르게 활용 가능합니다.
4️⃣ QuerySet에서 .count()
와 .exists()
는 즉시 평가된다!
Django QuerySet은 기본적으로 지연 평가되지만, 일부 메서드는 자동으로 즉시 평가를 실행합니다.
.count()
(즉시 쿼리 실행)
post_count = Post.objects.filter(status='PB').count()
# ✅ 즉시 쿼리 실행됨 (SELECT COUNT(*) FROM post WHERE status='PB';)
.exists()
(즉시 쿼리 실행)
has_published_posts = Post.objects.filter(status='PB').exists()
# ✅ 즉시 쿼리 실행됨 (SELECT 1 FROM post WHERE status='PB' LIMIT 1;)
.count()
와 .exists()
는 QuerySet을 변환하지 않아도 즉시 실행됩니다.
5️⃣ Lazy Evaluation vs. Eager Evaluation 비교 정리
Lazy Evaluation (지연 평가) | Eager Evaluation (즉시 평가) | |
---|---|---|
설명 | 필요할 때까지 쿼리를 실행하지 않음 | 즉시 쿼리를 실행하고 데이터를 가져옴 |
예제 | QuerySet 상태 유지 |
list(QuerySet) , .values_list() , .count() |
장점 | 불필요한 DB 쿼리를 방지, 메모리 절약 | DB 조회 후 빠르게 데이터 활용 가능 |
단점 | 필요할 때마다 쿼리 실행 가능성 있음 | DB 부하가 즉시 발생, 추가 ORM 연산 불가능 |
사용 예시 | .filter() , .annotate() , .order_by() |
list() , .count() , .exists() , .values() |
즉시 평가 (list(QuerySet)
)를 적용하면 데이터가 즉시 로드되고, 추가적인 DB 쿼리를 방지할 수 있습니다!
하지만 QuerySet 기능을 더 이상 사용할 수 없으므로, 언제 적용할지 신중히 결정해야 합니다!
📌 결론
✅ Django의 QuerySet은 기본적으로 Lazy Evaluation (지연 평가)를 따른다.
✅ 즉시 평가(Eager Evaluation)를 사용하면 DB에서 데이터를 즉시 가져오고 QuerySet이 리스트로 변환됨.
✅ .values()
, .values_list()
를 list()
로 감싸면 즉시 평가됨.
✅ Lazy Evaluation을 유지하면 불필요한 DB 쿼리를 방지할 수 있지만, 때로는 즉시 평가가 더 적절할 수도 있다!
Add a New Comment