MongoEngine QuerySet의 .only() 메서드를 통한 필드 프로젝션 및 성능 최적화

MongoEngine에서 QuerySet을 다룰 때 .only() 메서드는 특정 필드만 선택적으로 가져오는 필드 프로젝션(Field Projection)을 수행하여 쿼리 성능을 최적화하는 데 사용됩니다. 이 메서드의 내부 동작 방식과 반환되는 데이터의 특성에 대해 살펴보겠습니다.

.only() 메서드의 핵심 동작

.only('field_name')은 MongoDB 수준에서 반환될 필드를 제한합니다. 이를 통해 불필요한 데이터 로딩을 방지하고 메모리 사용량과 네트워크 전송량을 크게 줄일 수 있습니다.

모델 정의 및 데이터 조회 예제

다음과 같은 사용자 활동 로그를 저장하는 문서 모델이 있다고 가정해 보겠습니다.

from mongoengine import Document, StringField, DateTimeField, DictField
import datetime

class ActivityLog(Document):
    user_id = StringField(required=True)
    action = StringField(required=True)
    timestamp = DateTimeField(default=datetime.datetime.utcnow)
    payload = DictField()

이제 user_idaction 필드만 명시적으로 요청하는 쿼리를 실행합니다.

# 특정 필드만 프로젝션하여 조회
logs = ActivityLog.objects.only('user_id', 'action')

반환 결과 및 필드 접근 특성

위 쿼리의 결과로 반환되는 객체는 일반적인 QuerySet이지만, 내부 문서 객체는 제한된 필드만 포함하고 있습니다.

  • 기본 키(_id) 자동 포함: 명시적으로 지정하지 않더라도 MongoDB의 기본 동작에 따라 _id 필드는 항상 결과에 포함됩니다.
  • 지정된 필드 접근: user_idaction은 정상적으로 읽을 수 있습니다.
  • 미포함 필드 접근 시 예외: 프로젝션되지 않은 timestamppayload 필드에 접근하려고 하면 mongoengine.errors.ValidationError가 발생하며 프로그램이 중단됩니다.
for log in logs:
    print(log.id)         # 정상 출력: 기본 키(_id) 값
    print(log.user_id)    # 정상 출력: 프로젝션된 user_id 값
    print(log.action)     # 정상 출력: 프로젝션된 action 값
    
    # 미로드 필드 접근 시 예외 발생
    # print(log.timestamp)  # mongoengine.errors.ValidationError 발생

주요 고려사항 및 활용 시나리오

1. 다중 필드 프로젝션

하나의 필드뿐만 아니라 쉼표로 구분하여 여러 필드를 동시에 지정할 수 있습니다.

partial_logs = ActivityLog.objects.only('user_id', 'action', 'timestamp')

2. 네트워크 및 메모리 최적화

문서의 크기가 크거나(예: payload에 대용량 JSON이 포함된 경우) 결과 집합이 방대할 때 .only()를 사용하면 네트워크 대역폭과 애플리케이션의 메모리 점유율을 획기적으로 낮출 수 있습니다.

3. 특정 목적의 데이터 집계

전체 문서가 아닌 특정 속성만을 활용한 통계나 집계 작업에 매우 유용합니다. 예를 들어, 특정 기간 동안의 고유 사용자 ID 목록을 추출할 때 다음과 같이 간결하게 작성할 수 있습니다.

unique_users = {log.user_id for log in ActivityLog.objects.only('user_id')}

태그: MongoEngine MongoDB python QuerySet FieldProjection

7월 16일 03:13에 게시됨