장고 ORM을 사용하다 보면 쿼리셋을 이용해서 쿼리를 처리하게 된다. 그런데 조금 이상한 것이 있다. 예를 들어, 아래 코드를 보자.
# views.py
data = DataModel.objects.all()
직관적으로 생각하면 실행 흐름은 data에 모든 데이터가 반환되어야 할 것 같다. 하지만 출력해보면 data역시 쿼리셋이다. 왜 ORM은 이렇게 동작할까?
# views.py
data = DataModel.objects.all()
sorted_data = data.order_by("-created_at")
위 코드를 보자. 만약 data가 모든 데이터라면 order_by
를 사용할 수 없어야 정상이다. 하지만 데이터베이스에 접근을 지연함으로서 나중에 추가될 수 있는 쿼리를 기다리는 것이다. 이것을 Lazy Loading이라 하는데 쿼리셋의 중요한 특징이다.
# views.py
sorted_data = DataModel.objects.all().order_by("-created_at")
이렇게 체이닝이 가능한 이유도 바로 Lazy Loading이 적용되고 있었기 때문이다.
이런 기능 덕분에 쿼리를 반복해서 실행하지 않기 때문에 효율적으로 데이터베이스에 접근할 수 있고 실행되기 전 쿼리셋에 여러 쿼리를 추가할 수 있으므로 유연하게 코드를 작성할 수 있다.
그렇다면, 쿼리가 실행되는 시점은 언제일까? 그것은 실제로 데이터를 사용하는 순간이다. 예를 들어, 아래와 같은 경우가 있다.
get
명령을 사용따라서 ORM과 이런 함수들을 함께 사용할 때는 쿼리가 중복해서 실행되지 않도록 검토해야 한다.
# views.py
data = DataModel.objects.all()
for d in data:
print(d)
sorted_data = data.order_by("-created_at")
for sd in sorted_data:
print(sd)
이렇게 코드를 작성하면 쿼리를 두 번 실행하게 되어 비효율적인 방식이 된다.