MongoDB 데이터베이스를 사용할때
엔티티 간의 관계에 따라서 어떤식으로 스키마를 구성하면 좋을지 직관적으로 따르기 좋은 가이드를 정리해본다.
MongoDB 스키마 디자인에서 첫번째 원칙은 다음과 같다.
mongodb 에서는 되도록 embedded document 로 데이터를 구성하는 것이 바람직하다.
{
_id: ObjectId("AAA"),
name: "Joe Karlsson",
identity: {
idNumber: "1123519",
registeredAt: "2023-01-01 09:30:00",
},
}
위에서 언급한 Rule 1
에 따라서 embedded document 방식으로 구성할 수 있으면 embedded document 를 사용하는 것이 좋다.
{
_id: ObjectId("AAA"),
name: "Joe Karlsson",
identity: {
idNumber: "1123519",
registeredAt: "2023-01-01 09:30:00",
},
company: "MongoDB",
twitter: "@JoeKarsson1",
twitch: "joe_karlsson",
website: "joekarlsson.com",
addresses: [
{ street: "123 Sesame St", city: "Anytown", cc: "USA" },
{ street: "123 Avenue Q", city: "New York", cc: "USA" },
]
}
어떤 사용자가 여러 개의 집을 갖고 있는 경우 또는 집과 사무실을 모두 자신의 주소로 등록하는 경우 주소 데이터는 Array 형태가 된다.
위에서 언급한 Rule 1
에 따라서 embedded document 방식으로 구성할 수 있으면 embedded document 를 사용하는 것이 좋다.
mongodb 에서 어떤 데이터를를 embedded document 로 구성하려고 했는데
나중에 알고보니 그 embedded document 를 감싸고 있는 부모 도큐멘트 없이 사용할 필요가 생긴다면
해당 데이터는 별로의 스키마로 구성하는 것이 바람직하다.
{
_id: ObjectId("123"),
name: "steering wheel",
manufacturer: "Acme Corp",
catalog_number: 1234,
parts: [
ObjectId("BBB"),
ObjectId("CCC"),
ObjectId("DDD")
]
}
[
{
_id: ObjectId("BBB"),
partNo: "123-ABC-456",
name: "#1 steering wheel handle right",
qunatity: 94,
cost: 0.54,
price: 2.99
},
{
_id: ObjectId("CCC"),
partNo: "777-def-234",
name: "#2 steering wheel handle left",
qunatity: 102,
cost: 0.54,
price: 2.99
},
{
_id: ObjectId("DDD"),
partNo: "654-ein-19",
name: "#3 steering wheel handle middle",
qunatity: 99,
cost: 0.33,
price: 2.78
}
]
아래쪽의 도큐멘트는 개별 부품을 의미하고
위쪽의 도큐멘트는 여러개의 부품을 조합해서 만든 하나의 기계 파트를 의미한다.
제한된 개수의 어떤 대상과 One-To-Many 관계를 맺는 경우가 있다면 도큐멘트 id 를 참조해서 embedded array 방식으로 다루면 된다.
mongodb 에서 JOIN 이나 $lookup 실행에 비용이 많이 든다는 것은 사실이지만
별도의 스키마로 구성하는 것이 디자인 상으로 더 바람직한 설계라는 판단이 선다면 별도의 스키마로 구성하는 것을 망설일 필요는 없다.
{
_id: ObjectId("RRR"),
name: "goofy.example.com",
ipAddr: "127.66.66.66"
}
[
{
_id: ObjectId("abcd1234"),
time: ISODate("2023-03-28T11:30:41.382Z"),
message: "The CPU is on fie!!!",
host: ObjectId("RRR")
},
{
_id: ObjectId("abcd5678"),
time: ISODate("2023-04-01T16:50:22.177Z"),
message: "Drive is hosed",
host: ObjectId("RRR")
},
...
]
위의 예시는 로그 데이터이고 로그 데이터는 일반적으로 무한히 증가한다.
이런 경우에는 참조의 방향을 뒤집어서 squillion 쪽의 개별 도큐멘트가 one 쪽의 도큐멘트를 참조하도록 구성하면 좋다.
mongodb 를 사용할때 무조건 기억해야 하는 제약사항은 개별 도큐멘트의 최대 크기는 16MB 라는 사실이다.
그러므로 Array 가 무한히 늘어날 것 같다면 무조건 여기와 비슷한 방식으로 구성해야 한다.
[
{
_id: ObjectId("AAF11"),
name: "Joe Karlsson",
tasks: [
ObjectId("FAD9"),
ObjectId("FC02"),
ObjectId("ZP17")
]
},
{
_id: ObjectId("AAE23"),
name: "Joe Karlsson",
tasks: [
ObjectId("FAD9"),
ObjectId("FC02"),
ObjectId("ZP17")
]
}
]
[
{
_id: ObjectId("FAD9"),
description: "Learn MongoDB",
dueDate: ISODate("2023-01-07T10:00:00.915Z"),
owners: [
ObjectId("AAF11"),
ObjectId("AAE23"),
]
},
{
_id: ObjectId("FC02"),
description: "Learn Mongoose",
dueDate: ISODate("2023-02-22T18:00:00.306Z"),
owners: [
ObjectId("AAF11"),
]
},
]
사실 이 다섯번째 원칙이 가장 중요하다고 할 수도 있는데
NoSQL 이 등장한 이유중의 하나는 데이터를 어떻게 구성하고 저장하는지 보다는 애플리케이션 로직에 집중해서 애플리케이션 로직을 보다 효율적으로 구현하자는 의도였다.
위에서 언급한 One-to-Squillions 관계를 다루는 다른 방식이 있다.
[
{
_id: ObjectId("KimKardashian9876"),
displayName: "Kim Kardashian West",
followers_count: "64500485",
followers: [
ObjectId("KrysJenner"),
ObjectId("CaitlynJenner"),
ObjectId("JustinBeaver"),
...
],
hasExtras: true
},
{
_id: ObjectId("KimKardashian79102"),
origin: ObjectId("KimKardashian9876"),
isOverflow: true,
followers: [
ObjectId("KanyeWest"),
ObjectId("EllenPage"),
ObjectId("AnneHathaway"),
...
],
hasExtras: true
},
]
이런식으로 embedded array 처럼 다루지만
추가 데이터가 있다는 것을 hasExtras 를 사용해서 표시하고 이전 데이터에서 이어진다는 것을 isOverflow 를 사용해서 표시하는 방법이 있다.
이와 같은 독특한 여러가지 패턴은 MongoDB Schema Design Pattern 이라는 이름으로 정리되어 있다.
다음 링크에서 확인할 수 있다.
Building with Patterns: A Summary
출처
[1] MongoDB University - M320: Introduction to MongoDB Data Modeling: https://learn.mongodb.com/courses/introduction-to-mongodb-data-modeling
[2] How To Design a Document Schema in MongoDB: https://www.digitalocean.com/community/tutorials/how-to-design-a-document-schema-in-mongodb
[3] Building With Patterns: The Outlier Pattern: https://www.mongodb.com/blog/post/building-with-patterns-the-outlier-pattern
[4] MongoDB Schema Design Best Practices: https://youtu.be/leNCfU5SYR8
[5] Data Modeling with MongoDB: https://youtu.be/3GHZd0zv170
[6] A Complete Methodology of Data Modeling for MongoDB: https://youtu.be/DUCvYbcgGsQ
[7] Advanced Schema Design Patterns: https://youtu.be/bxw1AkH2aM4
와.... 요즘 쉬시는 척 하시더니 또또 공부... 역시 진짜 후.....