ORM의 한계? Raw Query 사용 방법과 시점

Django ORM은 강력하지만 극도로 복잡한 쿼리, 성능 병목 구간, DB 고유 기능 활용 시에는 한계가 존재. 이러한 상황에서 Raw Query를 사용하되, ORM 최적화를 먼저 시도한 후 신중하게 결정해야 함

ORM의 한계 상황

극도로 복잡한 쿼리

  • 여러 모델의 복잡한 JOIN과 통계, 중첩 서브쿼리가 필요한 경우

  • 재귀적 구조 데이터 처리(재귀 CTE)

  • ORM으로 표현 시 가독성이 현저히 떨어지는 경우

성능 병목 구간

  • ORM이 생성한 SQL보다 최적화된 쿼리가 필요한 경우

  • 트래픽이 몰리는 핵심 API에서 1ms라도 단축이 필요한 상황

데이터베이스 고유 기능 활용

  • PostgreSQL: Window Functions, JSONB 고급 함수, PostGIS

  • MySQL: Full-Text Search 특정 모드

  • 특정 인덱스 타입 활용

Raw Query 사용 방법

Manager.raw() - 모델 인스턴스 반환

# 올바른 파라미터 바인딩 사용
people = Person.objects.raw(
    "SELECT id, first_name, last_name FROM myapp_person WHERE last_name = %s",
    [last_name_to_find]
)

connection.cursor() - 직접 DB 접근

from django.db import connection

with connection.cursor() as cursor:
    cursor.execute(
        "SELECT first_name, last_name FROM myapp_person WHERE birth_date > %s",
        ['2000-01-01']
    )
    rows = cursor.fetchall()

사용 시 주의사항

SQL 인젝션 방지

  • 절대 f-string이나 % 포매팅으로 쿼리 작성 금지

  • 항상 params 인자나 execute()의 두 번째 인자 사용

최후의 보루로 사용

  • ORM 최적화(select_related, prefetch_related, annotate) 먼저 시도

  • DB 인덱스와 캐싱 검토 후 사용

커스텀 Manager 캡슐화

  • View 코드에 Raw Query 직접 노출 방지

  • 재사용성과 테스트 용이성 확보

Last updated