Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FAQ] QuerySet으로 원하는 SQL이 안 만들어져요 #8

Open
KimSoungRyoul opened this issue Sep 20, 2020 · 0 comments
Open

[FAQ] QuerySet으로 원하는 SQL이 안 만들어져요 #8

KimSoungRyoul opened this issue Sep 20, 2020 · 0 comments

Comments

@KimSoungRyoul
Copy link
Owner

KimSoungRyoul commented Sep 20, 2020

Django에서 개발자는 QuerySet을 통해 SQL을 작성한다.
그리고 SQL을 작성하는 주도권은 개발자가 아닌 QuerySet에게 있다는 것을 인지해야한다.

이는 Django QuerySet 뿐만 아니라 ORM 프레임워크들의 고질적인 문제다.

  • 개발자가 원하는 SQL을 작성할수 없다는 것(힘들다는 것)

이런 이슈를 해결하기위해 Java 진영에는 JPQL, QueryDSL(SQL DSL임)이 생겨났다.

DSL: Domain Specific Language ( 쉽게 생각하면 SQL DSL이란 애플리케이션 언어(Python, Java)로 작성하는 SQL)
// QueryDSL 쿼리 예제
//  SQL개념인 JOIN이  Java 메서드로 존재하는 걸 볼수있다
QCustomer customer = QCustomer.customer;
QCompany company = QCompany.company;
query.from(customer)
    .innerJoin(customer.company, company)
    .list(customer.firstName, customer.lastName, company.name);

그리고 Python ORM 오픈소스인 SQLAlchemy는 ORM쿼리 설계자체가 SQL DSL에 가까운 구조를 가지고있다.
이 덕분에 Django QuerySet 보다는 SQL 주도권이 개발자에게 더 많이 주어진다. (개인적인 경험과 생각)

# SQLAlchemy 쿼리 작성예제
# QueryDSL과 마찬가지로 JOIN이라는 SQL개념이 Python메서드로 드러나있다
session.query(Post) \
       .join(User, User.id == Post.author_id) \
       .filter(~User.deleted) \
       .filter(User.last_login_time > now() - datetime.timedelta(days=1))

그러나 Django ORM에는 이런 SQL DSL이 존재하지 않는다.

# 비록 여러번에 걸쳐서 select_related()이 JOIN이다 라고 설명했지만 
# JOIN이라는 SQL문법에 직결되지 않는다. 
# QueryDSL과 SQLAlchemy의 join()메서드는 JOIN SQL문자열을 추가한다는 개념이지만
# select_related는 여러 옵션들의 합친후 QuerySet.query에  JOIN을 부여 할지말지 여부를 QuerySet이 판단한다. 
# ex:  aggregate(), values() values_list() 같은 옵션 쓰면 JOIN 안할수도 있음
# 즉 SQL 작성 주도권이 QuerySet에게 있고 개발자에게 없다는 뜻
product_queryset = (Product.objects
     .select_related("company")
     .filter(company_name="blabla...")
     .prefetch_related("deliveryhistory_set")
 )

그렇기때문에 QuerySet을 설명할때 매번 아래 2가지를 강조하는 것이 그 이유다.

  • 원하는 SQL을 작성하려고 하지말고 원하는 데이터의 조건들을 먼저 생각하라는 것 (SQL주도권이 없기때문에)
  • QuerySet이 생성하는 기본SQL구조에서 벗어나는가? (Y/ N) QuerySet이 생성하는 SQL 구조 링크

바꿔 말하면 Django ORM은 완전 SQL 작성 주도권을 위임했기 때문에 개발자가 신경쓰지 않아도 된다는 장점으로 해석 할 수도 있다.

따라서 프로젝트를 시작할때 프레임워크로 Django를 선택지에 두고있다면

  • 프로젝트내 SQL들이 단조로운가?
  • 성능을 약간 포기하는 SQL도 허용될수 있는가?

이 점을 반드시 한번 생각해보자 (물론 ORM들이 다 그렇지만 Django는 더욱...!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant