MongoEngine에서의 참조, 임베디드, 지연 참조 필드 비교 및 활용 전략

1. ReferenceField: 외부 문서 참조

관계형 데이터베이스의 외래키와 유사하게, 하나의 문서가 다른 문서를 참조하는 방식입니다. 참조 대상의 ObjectId만 저장되며, 접근 시 실제 문서를 조회합니다.

  • 저장 구조: 참조 대상의 고유 식별자(예: ObjectId)만 저장됨.
  • 쿼리 동작: 필드 접근 시 즉시 타겟 문서를 조회하여 로드.
  • 적합한 상황: 참조 대상이 독립적으로 관리되며, 여러 문서에서 공유되는 경우.
from mongoengine import Document, StringField, ReferenceField

class Publisher(Document):
    name = StringField()

class Article(Document):
    title = StringField()
    publisher = ReferenceField(Publisher)  # 출판사 문서 참조

사용 예시:

publisher = Publisher(name="Tech Press").save()
article = Article(title="AI Trends", publisher=publisher).save()

# 접근 시 자동으로 참조 문서 조회
print(article.publisher.name)  # 출력: "Tech Press"

2. EmbeddedDocumentField: 내장 문서 구조

하나의 문서 내에 다른 문서를 직접 포함하여 저장하는 방식입니다. 모든 데이터는 부모 문서의 BSON에 함께 저장됩니다.

  • 저장 방식: 중첩된 문서 데이터가 부모 문서와 함께 저장됨.
  • 쿼리 특성: 부모 문서 조회 시 자동으로 내장 데이터 포함.
  • 제약 조건: 내장 문서는 별도로 참조할 수 없으며, 독립적인 컬렉션을 갖지 않음.
from mongoengine import Document, StringField, EmbeddedDocument, EmbeddedDocumentField

class ContactInfo(EmbeddedDocument):
    email = StringField()
    phone = StringField()

class Profile(Document):
    username = StringField()
    contact = EmbeddedDocumentField(ContactInfo)

사용 예시:

contact = ContactInfo(email="alice@example.com", phone="123-4567")
profile = Profile(username="alice", contact=contact).save()

# 바로 접근 가능
print(profile.contact.email)  # 출력: "alice@example.com"

3. LazyReferenceField: 지연 참조 처리

ReferenceField와 유사하지만, 참조 대상을 실제로 사용할 때까지 로드하지 않는 지연 로딩 기능을 제공합니다. 성능 최적화에 적합합니다.

  • 저장 형식: 참조 대상의 ObjectId 저장.
  • 로딩 전략: 접근 시 fetch() 호출로만 실제 문서를 불러옴.
  • 장점: 자주 사용되지 않는 참조 데이터는 무시되어 쿼리 부담 감소.
from mongoengine import Document, StringField, LazyReferenceField

class Contributor(Document):
    fullname = StringField()

class Project(Document):
    name = StringField()
    lead = LazyReferenceField(Contributor)

사용 방법:

contributor = Contributor(fullname="Bob Smith").save()
project = Project(name="API Service", lead=contributor).save()

# 지연 로딩: 필요한 순간에만 데이터 조회
print(project.lead.fetch().fullname)  # fetch() 실행 후 출력: "Bob Smith"

비교 요약표

구분 ReferenceField EmbeddedDocumentField LazyReferenceField
저장 방식 ObjectId 저장 내부 데이터 직접 포함 ObjectId 저장
데이터 로딩 시점 접근 시 즉시 로드 부모 문서 조회 시 자동 포함 필드 접근 시 fetch()로 지연 로드
성능 영향 항상 추가 쿼리 발생 단일 쿼리로 전체 데이터 획득 불필요한 쿼리 방지 가능
문서 간 결합도 낮은 결합도 (독립적) 높은 결합도 (강결합) 낮은 결합도 (독립적)
문서 크기 작은 크기 유지 부모 문서 크기 증가 작은 크기 유지
적합한 사용 사례 공유되며 독립적으로 관리되는 데이터 항상 함께 사용되는 작은 구조적 데이터 희소 접근, 성능 최적화 필요 시

추천 활용 전략

  • ReferenceField: 출판사, 사용자, 카테고리 등 여러 문서에서 공유되는 정보. 독립적인 수정과 관리가 필요한 경우.
  • EmbeddedDocumentField: 프로필의 연락처, 주소, 설정 항목처럼 부모와 밀접하게 연결된 작은 데이터 구조.
  • LazyReferenceField: 대량의 참조 데이터(예: 고객 정보)가 있지만 대부분의 조회에서는 사용하지 않는 경우. 성능 향상을 위해 지연 로딩이 필요할 때.

태그: MongoEngine ReferenceField EmbeddedDocumentField LazyReferenceField MongoDB

6월 4일 00:55에 게시됨