[MONGO]몽고디비 데이터 관계 모델링

startingfindmistake·2025년 12월 18일

몽고디비 관계 데이터 방식

몽고디비의 컬렉션간의 관계(조인) 데이터를 가져올때 대표적으로 2가지 방식 종류가 있다.



Dcument - Embedded

Embedded 저장 방법은 2가지 종류의 Document가 있을 때, 1개의 Document 데이터를 Document key의 value에 통짜로 저장하는 방법이다.

예를 들어, 여기 2가지 종류의 Person Document 와 Address Document가 있다고 하자.

// Person 
{
	_id: "joe",
    name: "Joe piter"
}

// Address
{
   pataron_id: "joe",
   street: "123 Fake Street",
   city: "Faketon",
   state: "MA",
   zip: "12345"
}

위의 Document를 Embedded 방식으로 관계를 저장하면 다음과 같이 된다.

Person.address 에 Address Document가 통째로 저장되어 있는 것을 볼 수 있다.

// Person 
{
   _id: "joe",
   name: "Joe Bookreader",
   
   address: { // Address
      street: "123 Fake Street",
      city: "Faketon",
      state: "MA",
      zip: "12345"
  }
}



Document - Reference

Reference 저장 방법은 pointer 개념으로 이해하면 된다.
Embedded 방식의 Document를 통째로 저장하는것이 아니라 참조 할 수 있도록 ID를 저장하는 방식이다.

예를들어, 2가지 종류의 Publisher Document / Book Document가 있을때, Book Document의 publisher_id에 Publisher._idvalue를 저장 하는 것이다.

RDBMS의 외래키와 같은 개념이라고 봐도 되며,
이렇게 _id를 저장해주면 몽고디비가 알아서 찾아 연결해준다.

// Publisher
{
   _id: "oreilly", // <- Publisher._id
   name: "O'Reilly Media",
   founded: 1980,
   location: "CA"
}



// Book
{
   _id: 123456789,
   title: "MongoDB: The Definitive Guide",
   author: [ "Kristina Chodorow", "Mike Dirolf" ],
   published_date: ISODate("2010-09-24"),
   pages: 216,
   language: "English",

   publisher_id: "oreilly" // <- Publisher._id
}

몽고디비 관계 유형


One-to-One 방식

단순한 1:1 관계이다.

RDBMS는 테이블을 나누어 표현했지만, NOSQL은 하나의 다큐먼트에 그대로 표현이 가능하다.

// 두개의 테이블로 나누어 1:1 관계를 맺는게 아니라, 몽고디비는 그냥 도큐먼트에 키값을 저장해버리면 된다.
{
 "emp_id" : 1001,
 "emp_name" : "홍길동", 
 "reg_number" : "111111-1111111"
}

One-to-Many 방식

1:N 관계 이며 여기서 위에서 배운 몽고디비 관계 데이터 2가지 방식에 따라 장단점이 갈리게 된다.

다음과 같이 1개의 Publisher Document와 2개의 Book Document가 있다고 가정하자.

Embedded 방식으로 했을 때, 위에서 배운바와 같이 데이터 구조는 Book.publisher의 value에 Publisher데이터가 통째로 저장되게 된다.

가장 단순한 기법이지만 중복 데이터가 발생해 쓸데없이 도큐먼트 크기가 커진다는 단점이 있다.

/* *** Publisher 컬렉션 *** */

// Publisher 1 다큐먼트
{
   _id: "oreilly",
   name: "O'Reilly Media",
   founded: 1980,
   location: "CA"
}

/* *** Book 컬렉션 *** */

// Book 1 다큐먼트
{
   _id: 123456789,
   title: "MongoDB: The Definitive Guide",
   author: [ "Kristina Chodorow", "Mike Dirolf" ],
   published_date: ISODate("2010-09-24"),
   pages: 216,
   language: "English",

   publisher: { // 통째로 그대로 저장되어있다. 중복 발생
      name: "O'Reilly Media",
      founded: 1980,
      location: "CA"
   }
}

// Book 2 다큐먼트
{
   _id: 234567890,
   title: "50 Tips and Tricks for MongoDB Developer",
   author: "Kristina Chodorow",
   published_date: ISODate("2011-05-06"),
   pages: 68,
   language: "English",

   publisher: { // 통째로 그대로 저장되어있다. 중복 발생
      name: "O'Reilly Media",
      founded: 1980,
      location: "CA"
   }
}

반면 Reference 방식으로 했을 때는 2개의 Book.publisher_id의 value에 각각 Publisher_id의 value만 저장되어 있게 된다.

/* *** Publisher 컬렉션 *** */

// Publisher 1 다큐먼트
{
   _id: "oreilly",
   name: "O'Reilly Media",
   founded: 1980,
   location: "CA"
}

/* *** Book 컬렉션 *** */

// Book 1 다큐먼트
{
   _id: 123456789,
   title: "MongoDB: The Definitive Guide",
   author: [ "Kristina Chodorow", "Mike Dirolf" ],
   published_date: ISODate("2010-09-24"),
   pages: 216,
   language: "English",

   publisher_id: "oreilly" // <- Publisher._id
}

// Book 2 다큐먼트
{
   _id: 234567890,
   title: "50 Tips and Tricks for MongoDB Developer",
   author: "Kristina Chodorow",
   published_date: ISODate("2011-05-06"),
   pages: 68,
   language: "English",

   publisher_id: "oreilly" // <- Publisher._id
}




Many-to Many

Many-to-Many는 One-to-Many 관계에서 확장된 m:n 관계 유형이다.
One-to-Many에서 Publisher : Book = 1 : n 이었지만,
Many-to-Many는 m : n 이 가능한 구조이다.


아례 예시를 보시면 Book.publisher_id value가 1개 이상의 Publisher.id를 참조하고 있는걸 볼 수 있다.

/* *** Publisher 컬렉션 *** */

// Publisher 1 다큐먼트
{
   _id: "oreilly",
   name: "O'Reilly Media",
   founded: 1980,
   location: "CA"
}

// Publisher 2 다큐먼트
{
   _id: "devhak",
   name: "devhak'Reilly Media",
   founded: 1980,
   location: "CA"
}

/* *** Book 컬렉션 *** */

// Book 1 다큐먼트
{
   _id: 123456789,
   title: "MongoDB: The Definitive Guide",
   author: [ "Kristina Chodorow", "Mike Dirolf" ],
   published_date: ISODate("2010-09-24"),
   pages: 216,
   language: "English",

   publisher_id: ["oreilly", "devhak"] // <- Publisher._id 여러개 참조
}

// Book 2 다큐먼트
{
   _id: 234567890,
   title: "50 Tips and Tricks for MongoDB Developer",
   author: "Kristina Chodorow",
   published_date: ISODate("2011-05-06"),
   pages: 68,
   language: "English",

   publisher_id: ["oreilly", "devhak"] // <- Publisher._id 여러개 참조
}



Embedded vs Reference 관계 장단점

먼저 One-to-Many(1:N)관계에서 Embedded 와 Reference 방식을 각각 비교해보자.

만약 publisher 컬렉션에 'name' 키를 변경하거나 'age' 라는 키를 추가해야 하는 경우에 컬렉션 자체를 업데이트해야 되는데,
그러면 관계를 맺은 컬렉션 역시 수정을 해야 되는데 관계 데이터 방식에 따라 다르게 된다.


  • Embedded방식으로 저장된 데이터는 Publisher, Book 의 Document를 모두 수정해서 데이터의 일관성을 유지해야 한다. 따라서 복잡하거나 데이터가 자주 변경되는 상황이 생긴다면 일관성을 유지하기가 어려워 질 수 있다.

  • Reference방식으로 저장된 데이터는 Publisher Document 만 수정해주면 어처피 ID만 참조하고 있기 때문에 모든 Document는 수정할 필요가 없다.
    자연스럽게 데이터의 일관성이 유지가 된다.

이렇게 보면 무조건 Reference 관계 데이터 방식이 효율적으로 보일수도 있겠지만, 반면에 이러한 가정도 있다.

다음과 같이 Document마다 모두 관계가 저장되어 있다고 하자.

  • Publisher Document개수: 100개
  • Book Document개수: 100만개

극단적으로 100만개의 Book Document를 Publisher 정보를 포함하여 불러오려고 할 때,

  • Embedded방식으로 저장된 데이터는 퍼포먼스 저하 없이 Publisher 정보를 통째로 가져올 수 있다.

  • Reference방식으로 저장된 데이터는 Publisher_id에 해당되는 Publisher 정보를 포함하도록 요청해서 가져와야 하기 때문에 추가적인 요청을 해야만 Publisher 정보를 가져 올 수 있게 된다.
    즉, 100만개의 Book Document를 조회해야한다면 100만번의 관계 포함 요청을 보내야 된다는 말과 같다.
    당연히 이럴 경우 퍼포먼스 저하가 일어나게 된다.

따라서 정리하자면, Embedded 또는 Reference 둘 중 어떠한 저장 방법이 효율적일지는 서비스의 기획에 따라 달라지게 된다.


Embedded vs Reference 모델 특징

Embedded모델

  • 16MB 제한
  • 빈번한 업데이트, 크기가 증가하는 업데이트일 때는 권장하지 않음 -> 단편화
  • 대신 읽기 속도 향상 : 한번의 쿼리로 조회


Reference 모델

  • 더 복잡하지만 유연한 데이터 구조
  • 데이터 크기 제한 없음
  • 상대적으로 강한 일관성 제공 가능

참고문헌
https://inpa.tistory.com/entry/MONGO-%F0%9F%93%9A-%EB%AA%BD%EA%B3%A0%EB%94%94%EB%B9%84%EC%9D%98-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B4%80%EA%B3%84-%EB%AA%A8%EB%8D%B8%EB%A7%81-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC

profile
도움이되었다면 그것으로 충분 합니다.

0개의 댓글