Ver3.0 ๐ฏ MongoDB ์คํค๋ง ์ค๊ณ์ ์ปฌ๋ ์ ์ต์ ํ

๐ฏ MongoDB ์คํค๋ง ์ค๊ณ์ ์ปฌ๋ ์ ์ต์ ํ
์น๊ตฌ์ฒ๋ผ ํธํ๊ฒ ๋ฐฐ์ฐ๋ NoSQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ์ ๋ชจ๋ ๊ฒ
์๋
! ์ค๋์ MongoDB๋ฅผ ์ฌ์ฉํ๋ฉด์ ๋๊ตฌ๋ ํ ๋ฒ์ฏค ๊ณ ๋ฏผํ๊ฒ ๋๋ ์คํค๋ง ์ค๊ณ์ ์ปฌ๋ ์
์ต์ ํ์ ๋ํด ์ด์ผ๊ธฐํด๋ณผ๊น ํด. ๐
์ฌ์ค MongoDB๋ฅผ ์ฒ์ ์ ํ๋ฉด "์ด? ์คํค๋ง๊ฐ ์๋ค๊ณ ? ๊ทธ๋ผ ๋ง ๋ฃ์ผ๋ฉด ๋๋ ๊ฑฐ ์๋?"๋ผ๊ณ ์๊ฐํ๊ธฐ ์ฌ์ด๋ฐ, ์ค์ ๋ก๋ ๊ทธ๋ ์ง ์์.
์คํ๋ ค ์์ ๋๊ฐ ๋์ ๋งํผ ๋ ์ ์คํ๊ฒ ์ค๊ณํด์ผ ๋์ค์ ์ฑ๋ฅ ๋ฌธ์ ๋ ์ ์ง๋ณด์ ์ง์ฅ์ ๋น ์ง์ง ์์ ์ ์์ง.
ํนํ ์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์์ ๋ค์ํ ์ฌ์ฉ์ ๋ฐ์ดํฐ์ ๊ฑฐ๋ ์ ๋ณด๋ฅผ ๋ค๋ฃฌ๋ค๋ฉด, ์ฒ์๋ถํฐ ์ ๋๋ก ๋ ์ค๊ณ๊ฐ ์ ๋ง ์ค์ํด.
๊ทธ๋์ ์ค๋์ ์ค๋ฌด์์ ๋ฐ๋ก ์จ๋จน์ ์ ์๋ MongoDB ์คํค๋ง ์ค๊ณ ์์น๋ถํฐ ์ปฌ๋ ์
์ต์ ํ ๊ธฐ๋ฒ๊น์ง ์ฐจ๊ทผ์ฐจ๊ทผ ์์๋ณผ ๊ฑฐ์ผ. ๐
- โ MongoDB์ ์คํค๋ง ์ค๊ณ ์ฒ ํ๊ณผ ๊ด๊ณํ DB์์ ์ฐจ์ด์
- โ ์๋ฒ ๋๋ vs ๋ ํผ๋ฐ์ค ํจํด ์ ํ ๊ธฐ์ค
- โ ์ค์ ์คํค๋ง ์ค๊ณ ํจํด๊ณผ ์ํฐํจํด
- โ ์ธ๋ฑ์ค ์ ๋ต๊ณผ ์ฟผ๋ฆฌ ์ต์ ํ
- โ ์ปฌ๋ ์ ์ค๋ฉ๊ณผ ๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
- โ ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง๊ณผ ํ๋ ํ
๐จ MongoDB ์คํค๋ง ์ค๊ณ์ ์ฒ ํ
๋จผ์ MongoDB์ ์คํค๋ง ์ค๊ณ ์ฒ ํ๋ถํฐ ์ดํดํด๋ณด์.
๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค(RDBMS)๋ฅผ ์ฌ์ฉํด๋ดค๋ค๋ฉด, ์ ๊ทํ(Normalization)๋ผ๋ ๊ฐ๋
์ ์ต์ํ ๊ฑฐ์ผ.
๋ฐ์ดํฐ ์ค๋ณต์ ์ต์ํํ๊ณ , ํ
์ด๋ธ์ ์๊ฒ ์ชผ๊ฐ์ JOIN์ผ๋ก ์ฐ๊ฒฐํ๋ ๋ฐฉ์ ๋ง์ด์ผ.
ํ์ง๋ง MongoDB๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐ์ดํฐ ์ ๊ทผ ํจํด์ ์ค์ฌ์ผ๋ก ์ค๊ณํด์ผ ํด.
"์ด ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ์กฐํํ ๊ฒ์ธ๊ฐ?"๊ฐ ๊ฐ์ฅ ์ค์ํ ์ง๋ฌธ์ด์ง.
์๋ํ๋ฉด MongoDB๋ JOIN ์ฐ์ฐ์ด ์ ํ์ ์ด๊ณ (lookup์ ์์ง๋ง ์ฑ๋ฅ์ด ์ข์ง ์์), ์ฝ๊ธฐ ์ฑ๋ฅ์ ์ต์ฐ์ ์ผ๋ก ๊ณ ๋ คํ๊ธฐ ๋๋ฌธ์ด์ผ.
1. ํจ๊ป ์กฐํ๋๋ ๋ฐ์ดํฐ๋ ํจ๊ป ์ ์ฅํ๋ผ
๊ด๊ณํ DB์ฒ๋ผ ๋๋์ง ๋ง๊ณ , ์์ฃผ ๊ฐ์ด ์ฝํ๋ ๋ฐ์ดํฐ๋ ํ ๋ฌธ์์ ๋ฃ์ด.
2. ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฝ๊ธฐ/์ฐ๊ธฐ ๋น์จ์ ๊ณ ๋ คํ๋ผ
์ฝ๊ธฐ๊ฐ ๋ง์ผ๋ฉด ๋น์ ๊ทํ๋ฅผ, ์ฐ๊ธฐ๊ฐ ๋ง์ผ๋ฉด ์ ๊ทํ๋ฅผ ๊ณ ๋ คํด.
3. ๋ฌธ์ ํฌ๊ธฐ์ ์ฑ์ฅ ํจํด์ ์์ธกํ๋ผ
MongoDB ๋ฌธ์๋ ์ต๋ 16MB ์ ํ์ด ์์ด. ๋ฌดํ์ ์ปค์ง ์ ์๋ ๋ฐฐ์ด์ ์ฃผ์!
๐ ์๋ฒ ๋๋ vs ๋ ํผ๋ฐ์ค: ์์ํ ๊ณ ๋ฏผ
MongoDB ์คํค๋ง ์ค๊ณ์์ ๊ฐ์ฅ ๋ง์ด ๊ณ ๋ฏผํ๊ฒ ๋๋ ๋ถ๋ถ์ด ๋ฐ๋ก ์ด๊ฑฐ์ผ.
"๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ๋ฌธ์ ์์ ๋ฃ์๊น(์๋ฒ ๋๋), ์๋๋ฉด ๋ณ๋ ์ปฌ๋ ์
์ผ๋ก ๋ถ๋ฆฌํ๊ณ ์ฐธ์กฐํ ๊น(๋ ํผ๋ฐ์ค)?" ๐ค
์ ๋ต์... ์ํฉ์ ๋ฐ๋ผ ๋ค๋ฅด๋ค๋ ๊ฑฐ์ผ! (์ด๊ฒ ์ ์ผ ๋ต๋ตํ์ง? ใ
ใ
)
ํ์ง๋ง ๋ช
ํํ ์ ํ ๊ธฐ์ค์ด ์์ผ๋๊น ๊ฑฑ์ ํ์ง ๋ง.
๐ฆ ์๋ฒ ๋๋ ํจํด (Embedded Documents)
์๋ฒ ๋๋ ํจํด์ ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ํ๋์ ๋ฌธ์ ์์ ์ค์ฒฉ์ํค๋ ๋ฐฉ์์ด์ผ.
๋ง์น JSON ๊ฐ์ฒด ์์ ๋ ๋ค๋ฅธ ๊ฐ์ฒด๋ ๋ฐฐ์ด์ ๋ฃ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ.
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"name": "๊น๊ฐ๋ฐ",
"email": "dev@example.com",
"address": {
"street": "ํ
ํค๋๋ก 123",
"city": "์์ธ",
"zipcode": "06234"
},
"orders": [
{
"order_id": "ORD001",
"product": "MongoDB ์๋ฒฝ๊ฐ์ด๋",
"amount": 35000,
"date": ISODate("2024-01-15")
},
{
"order_id": "ORD002",
"product": "Node.js ์ค์ ํ๋ก์ ํธ",
"amount": 42000,
"date": ISODate("2024-01-20")
}
]
}
1. ์ผ๋์ผ(1:1) ๊ด๊ณ
์ฌ์ฉ์์ ์ฃผ์์ฒ๋ผ ํญ์ ํจ๊ป ์กฐํ๋๋ ๋ฐ์ดํฐ
2. ์ผ๋๋ค(1:N) ๊ด๊ณ ์ค "๋ค"๊ฐ ์ ์ ๊ฒฝ์ฐ
๋ธ๋ก๊ทธ ํฌ์คํธ์ ๋๊ธ(๋๊ธ์ด ์์ญ ๊ฐ ์ดํ์ผ ๋)
3. ์์ ๋ฐ์ดํฐ๊ฐ ๋ถ๋ชจ ์์ด ๋ ๋ฆฝ์ ์ผ๋ก ์กฐํ๋์ง ์๋ ๊ฒฝ์ฐ
์ฃผ๋ฌธ ํญ๋ชฉ์ ์ฃผ๋ฌธ ์์ด ์กฐํํ ์ผ์ด ๊ฑฐ์ ์์ง
4. ์์์ ์ ๋ฐ์ดํธ๊ฐ ํ์ํ ๊ฒฝ์ฐ
ํ ๋ฒ์ ์ฐ๊ธฐ ์์ ์ผ๋ก ๋ชจ๋ ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํด์ผ ํ ๋
์๋ฒ ๋๋ ํจํด์ ๊ฐ์ฅ ํฐ ์ฅ์ ์ ์ฝ๊ธฐ ์ฑ๋ฅ์ด์ผ.
ํ ๋ฒ์ ์ฟผ๋ฆฌ๋ก ๋ชจ๋ ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ผ๋๊น ์์ฒญ ๋น ๋ฅด์ง! โก
์ฌ๋ฅ๋ท์์ ์ฌ์ฉ์ ํ๋กํ๊ณผ ๊ธฐ๋ณธ ์ ๋ณด๋ฅผ ๋ณด์ฌ์ค ๋, ํ ๋ฒ์ ๋ค ๊ฐ์ ธ์ฌ ์ ์๋ค๋ฉด ์ฌ์ฉ์ ๊ฒฝํ์ด ํจ์ฌ ์ข์์ง ๊ฑฐ์ผ.
๋ฌธ์ ํฌ๊ธฐ ์ ํ: MongoDB๋ ๋ฌธ์๋น ์ต๋ 16MB๊น์ง๋ง ์ ์ฅ ๊ฐ๋ฅํด.
๋ฐฐ์ด์ด ๋ฌดํ์ ์ปค์ง ์ ์๋ค๋ฉด ์๋ฒ ๋๋๋ ์ํํด!
์ค๋ณต ๋ฐ์ดํฐ ๊ด๋ฆฌ: ๊ฐ์ ๋ฐ์ดํฐ๊ฐ ์ฌ๋ฌ ๋ฌธ์์ ์๋ฒ ๋๋๋๋ฉด,
์ ๋ฐ์ดํธํ ๋ ๋ชจ๋ ๋ฌธ์๋ฅผ ์ฐพ์์ ์์ ํด์ผ ํด.
์ฐ๊ธฐ ์ฑ๋ฅ: ํฐ ๋ฌธ์๋ฅผ ์์ฃผ ์ ๋ฐ์ดํธํ๋ฉด ์ฑ๋ฅ์ด ๋จ์ด์ง ์ ์์ด.
๐ ๋ ํผ๋ฐ์ค ํจํด (References)
๋ ํผ๋ฐ์ค ํจํด์ ๊ด๊ณํ DB์ ์ธ๋ํค(Foreign Key)์ฒ๋ผ,
๋ค๋ฅธ ๋ฌธ์์ ID๋ฅผ ์ฐธ์กฐํ๋ ๋ฐฉ์์ด์ผ.
// users ์ปฌ๋ ์
{
"_id": ObjectId("507f1f77bcf86cd799439011"),
"name": "๊น๊ฐ๋ฐ",
"email": "dev@example.com"
}
// orders ์ปฌ๋ ์
{
"_id": ObjectId("507f191e810c19729de860ea"),
"user_id": ObjectId("507f1f77bcf86cd799439011"),
"product": "MongoDB ์๋ฒฝ๊ฐ์ด๋",
"amount": 35000,
"date": ISODate("2024-01-15")
}
// ์กฐํํ ๋๋ $lookup ์ฌ์ฉ
db.users.aggregate([
{
$lookup: {
from: "orders",
localField: "_id",
foreignField: "user_id",
as: "user_orders"
}
}
])
1. ๋ค๋๋ค(N:M) ๊ด๊ณ
ํ์๊ณผ ์์ , ์ํ๊ณผ ์นดํ ๊ณ ๋ฆฌ์ฒ๋ผ ์๋ฐฉํฅ ๊ด๊ณ
2. ์ผ๋๋ค(1:N) ๊ด๊ณ ์ค "๋ค"๊ฐ ๋งค์ฐ ๋ง์ ๊ฒฝ์ฐ
์ฌ์ฉ์์ ๋ก๊ทธ ๋ฐ์ดํฐ(์์ฒ~์๋ง ๊ฑด)
3. ์์ ๋ฐ์ดํฐ๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ์์ฃผ ์กฐํ๋๋ ๊ฒฝ์ฐ
์ํ ์ ๋ณด๋ ์ฃผ๋ฌธ๊ณผ ๋ณ๊ฐ๋ก๋ ์์ฃผ ์กฐํ๋์ง
4. ๋ฐ์ดํฐ ์ค๋ณต์ ์ต์ํํด์ผ ํ๋ ๊ฒฝ์ฐ
๊ฐ์ ์ํ ์ ๋ณด๊ฐ ์์ฒ ๊ฐ ์ฃผ๋ฌธ์ ์ค๋ณต๋๋ฉด ๋นํจ์จ์ ์ด์ผ
๋ ํผ๋ฐ์ค ํจํด์ ์ฅ์ ์ ๋ฐ์ดํฐ ์ผ๊ด์ฑ๊ณผ ์ ์ฐ์ฑ์ด์ผ.
์ํ ์ ๋ณด๊ฐ ๋ฐ๋๋ฉด ํ ๊ณณ๋ง ์์ ํ๋ฉด ๋๊ณ , ๋ฌธ์ ํฌ๊ธฐ ์ ํ๋ ๊ฑฑ์ ์์ง.
ํ์ง๋ง ์กฐํํ ๋ $lookup์ ์ฌ์ฉํด์ผ ํด์ ์ฑ๋ฅ์ ์๋ฒ ๋๋๋ณด๋ค ๋จ์ด์ ธ. ๐ข
์ค๋ฌด์์๋ ์๋ฒ ๋๋์ ๋ ํผ๋ฐ์ค๋ฅผ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์!
์๋ฅผ ๋ค์ด, ์ฃผ๋ฌธ ๋ฌธ์์ ์ํ ID๋ ๋ ํผ๋ฐ์ค๋ก ์ ์ฅํ๋,
์์ฃผ ์กฐํ๋๋ ์ํ๋ช ๊ณผ ๊ฐ๊ฒฉ์ ์ค๋ ์ท์ผ๋ก ์๋ฒ ๋๋ํด๋๋ ๊ฑฐ์ผ.
์ด๋ ๊ฒ ํ๋ฉด ๋๋ถ๋ถ์ ์กฐํ๋ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋ฉด์,
์์ธ ์ ๋ณด๊ฐ ํ์ํ ๋๋ง ์ํ ์ปฌ๋ ์ ์ ์ฐธ์กฐํ ์ ์์ด.
๐ฏ ์ค์ ์คํค๋ง ์ค๊ณ ํจํด
์ด์ ์ค๋ฌด์์ ์์ฃผ ์ฌ์ฉ๋๋ ์คํค๋ง ์ค๊ณ ํจํด๋ค์ ์์๋ณด์.
MongoDB ๊ณต์ ๋ฌธ์์์๋ ๊ถ์ฅํ๋ ๊ฒ์ฆ๋ ํจํด๋ค์ด์ผ! ๐
๐ณ ๊ณ์ธต ๊ตฌ์กฐ ํจํด (Tree Pattern)
์นดํ
๊ณ ๋ฆฌ, ์กฐ์ง๋, ๋๊ธ ์ค๋ ๋์ฒ๋ผ ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ํํํ ๋ ์ฌ์ฉํด.
์ฌ๋ฌ ๋ฐฉ๋ฒ์ด ์๋๋ฐ, ์ํฉ์ ๋ง๊ฒ ์ ํํ๋ฉด ๋ผ.
๊ฐ ๋ ธ๋๊ฐ ๋ถ๋ชจ์ ID๋ง ์ ์ฅํ๋ ๋ฐฉ์. ๊ฐ์ฅ ๋จ์ํ๊ณ ์ง๊ด์ ์ด์ผ.
{
"_id": "MongoDB",
"parent": "Databases"
}
{
"_id": "Databases",
"parent": "Programming"
}
{
"_id": "Programming",
"parent": null
}
๋ถ๋ชจ๋ฅผ ์ฐพ๊ธฐ๋ ์ฝ์ง๋ง, ์์๋ค์ ์ฐพ์ผ๋ ค๋ฉด ์ฟผ๋ฆฌ๊ฐ ํ์ํด.
ํธ๋ฆฌ๋ฅผ ์์์ ์๋๋ก ํ์ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง๋ค๋ฉด ๋ค๋ฅธ ํจํด์ ๊ณ ๋ คํด๋ด.
๋ถ๋ชจ๊ฐ ์์๋ค์ ID ๋ฐฐ์ด์ ์ ์ฅํ๋ ๋ฐฉ์.
{
"_id": "Programming",
"children": ["Databases", "Web", "Mobile"]
}
{
"_id": "Databases",
"children": ["MongoDB", "PostgreSQL", "MySQL"]
}
์์์ ์ฐพ๊ธฐ๋ ์ฝ์ง๋ง, ์์์ด ๋๋ฌด ๋ง์ผ๋ฉด ๋ฐฐ์ด์ด ์ปค์ ธ์ ๋ฌธ์ ๊ฐ ๋ ์ ์์ด.
๋ฃจํธ๋ถํฐ ํ์ฌ ๋ ธ๋๊น์ง์ ์ ์ฒด ๊ฒฝ๋ก๋ฅผ ๋ฐฐ์ด๋ก ์ ์ฅํ๋ ๋ฐฉ์.
ํน์ ๋ ธ๋์ ๋ชจ๋ ํ์ ๋ ธ๋๋ฅผ ์ฐพ์ ๋ ์ ์ฉํด!
{
"_id": "MongoDB",
"ancestors": ["Programming", "Databases"],
"parent": "Databases"
}
// ํน์ ์นดํ
๊ณ ๋ฆฌ์ ๋ชจ๋ ํ์ ํญ๋ชฉ ์ฐพ๊ธฐ
db.categories.find({ ancestors: "Programming" })
์ฌ๋ฅ๋ท์ ์นดํ ๊ณ ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์๊ฐํด๋ณด์.
"IT/ํ๋ก๊ทธ๋๋ฐ > ์น๊ฐ๋ฐ > ํ๋ก ํธ์๋ > React"
Array of Ancestors ํจํด์ ์ฌ์ฉํ๋ฉด,
"IT/ํ๋ก๊ทธ๋๋ฐ" ์นดํ ๊ณ ๋ฆฌ์ ๋ชจ๋ ํ์ ์ฌ๋ฅ์ ํ ๋ฒ์ ์กฐํํ ์ ์์ด!
์ฌ์ฉ์๊ฐ ์นดํ ๊ณ ๋ฆฌ๋ฅผ ํ์ํ ๋ ์ฑ๋ฅ์ด ํจ์ฌ ์ข์์ง๊ฒ ์ง? ๐
๐ ๋ฒํท ํจํด (Bucket Pattern)
์๊ณ์ด ๋ฐ์ดํฐ๋ ๋ก๊ทธ์ฒ๋ผ ๋๋์ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์ ์ฅํ ๋ ์ฌ์ฉํ๋ ํจํด์ด์ผ.
๋ฐ์ดํฐ๋ฅผ ์ผ์ ๋จ์๋ก ๋ฌถ์ด์(๋ฒํท) ์ ์ฅํ๋ ๊ฑฐ์ง.
// ๋นํจ์จ์ ์ธ ๋ฐฉ๋ฒ: ๊ฐ ์ธก์ ๊ฐ๋ง๋ค ๋ฌธ์ ์์ฑ
{
"sensor_id": "sensor1",
"timestamp": ISODate("2024-01-15T10:00:00Z"),
"temperature": 22.5
}
{
"sensor_id": "sensor1",
"timestamp": ISODate("2024-01-15T10:01:00Z"),
"temperature": 22.7
}
// ... ์๋ฐฑ๋ง ๊ฐ์ ๋ฌธ์
// ๋ฒํท ํจํด: 1์๊ฐ ๋จ์๋ก ๋ฌถ๊ธฐ
{
"sensor_id": "sensor1",
"start_time": ISODate("2024-01-15T10:00:00Z"),
"end_time": ISODate("2024-01-15T11:00:00Z"),
"measurements": [
{ "timestamp": ISODate("2024-01-15T10:00:00Z"), "temp": 22.5 },
{ "timestamp": ISODate("2024-01-15T10:01:00Z"), "temp": 22.7 },
{ "timestamp": ISODate("2024-01-15T10:02:00Z"), "temp": 22.6 },
// ... 60๊ฐ์ ์ธก์ ๊ฐ
],
"count": 60,
"avg_temp": 22.8
}
๋ฌธ์ ์ ๊ฐ์: ์๋ฐฑ๋ง ๊ฐ โ ์๋ง ๊ฐ๋ก ์ค์ด๋ค์ด
์ธ๋ฑ์ค ํฌ๊ธฐ๊ฐ ์์์ง๊ณ ์ฟผ๋ฆฌ ์ฑ๋ฅ์ด ํฅ์๋ผ.
์ง๊ณ ๋ฐ์ดํฐ ์ฌ์ ๊ณ์ฐ: ํ๊ท , ํฉ๊ณ ๋ฑ์ ๋ฏธ๋ฆฌ ๊ณ์ฐํด๋๋ฉด
๋ถ์ ์ฟผ๋ฆฌ๊ฐ ํจ์ฌ ๋นจ๋ผ์ ธ.
๋ฉ๋ชจ๋ฆฌ ํจ์จ: ๊ด๋ จ ๋ฐ์ดํฐ๊ฐ ํ ๋ฌธ์์ ์์ด์
๋์คํฌ I/O๊ฐ ์ค์ด๋ค์ด.
์ฌ๋ฅ๋ท์์ ์ฌ์ฉ์ ํ๋ ๋ก๊ทธ๋ ๊ฑฐ๋ ํต๊ณ๋ฅผ ์ ์ฅํ ๋ ๋ฒํท ํจํด์ ์ฌ์ฉํ๋ฉด,
๋์๋ณด๋ ์ฑ๋ฅ์ด ์์ฒญ๋๊ฒ ๊ฐ์ ๋ ๊ฑฐ์ผ! ๐
๐ ํ์ฅ ํจํด (Extended Reference Pattern)
๋ ํผ๋ฐ์ค ํจํด์ ๋จ์ (์กฐํ ์ ์กฐ์ธ ํ์)์ ๋ณด์ํ๋ ํจํด์ด์ผ.
์์ฃผ ์ฌ์ฉ๋๋ ํ๋๋ง ๋ณต์ฌํด์ ์ ์ฅํ๋ ๊ฑฐ์ง.
// orders ์ปฌ๋ ์
{
"_id": ObjectId("..."),
"user": {
"id": ObjectId("507f1f77bcf86cd799439011"),
"name": "๊น๊ฐ๋ฐ", // ์์ฃผ ํ์๋๋ ์ ๋ณด๋ง ๋ณต์ฌ
"email": "dev@example.com"
// ์ ํ๋ฒํธ, ์ฃผ์ ๋ฑ ์์ธ ์ ๋ณด๋ ์ ์ธ
},
"product": {
"id": ObjectId("..."),
"name": "MongoDB ์๋ฒฝ๊ฐ์ด๋",
"price": 35000,
"thumbnail": "https://..."
// ์์ธ ์ค๋ช
, ์ฌ๊ณ ๋ฑ์ ์ ์ธ
},
"order_date": ISODate("2024-01-15"),
"status": "delivered"
}
์ด๋ ๊ฒ ํ๋ฉด ์ฃผ๋ฌธ ๋ชฉ๋ก์ ๋ณด์ฌ์ค ๋ ์ถ๊ฐ ์กฐํ ์์ด ๋ฐ๋ก ํ์ํ ์ ์์ด.
์ฌ์ฉ์ ์ด๋ฆ์ด๋ ์ํ๋ช
์ด ๋ฐ๋๋ ๊ฒฝ์ฐ๋ ๋๋ฌผ๊ณ , ๋ฐ๋๋๋ผ๋ ์ฃผ๋ฌธ ๋ด์ญ์ ๋น์์ ์ ๋ณด๋ฅผ ๋ณด์ฌ์ฃผ๋ ๊ฒ ๋ง์ผ๋๊น ๋ฌธ์ ์์ง! ๐
๊ณ์ธต ๊ตฌ์กฐ: ์นดํ ๊ณ ๋ฆฌ, ์กฐ์ง๋, ๋๊ธ โ Tree Pattern
์๊ณ์ด ๋ฐ์ดํฐ: ๋ก๊ทธ, ์ผ์ ๋ฐ์ดํฐ, ํต๊ณ โ Bucket Pattern
์์ฃผ ์กฐํ๋๋ ๊ด๊ณ: ์ฃผ๋ฌธ-์ฌ์ฉ์, ๊ฒ์๊ธ-์์ฑ์ โ Extended Reference
๋คํ์ฑ ๋ฐ์ดํฐ: ์ฌ๋ฌ ํ์ ์ ์ ํ โ Polymorphic Pattern
๋ฒ์ ๊ด๋ฆฌ: ๋ฌธ์ ์ด๋ ฅ ์ถ์ โ Document Versioning Pattern
โ ๏ธ ํผํด์ผ ํ ์ํฐํจํด
์ข์ ํจํด๋งํผ ์ค์ํ ๊ฒ ๋์ ํจํด์ ํผํ๋ ๊ฒ์ด์ผ.
์ค๋ฌด์์ ์์ฃผ ๋ณด๋ ์ํฐํจํด๋ค์ ์์๋ณด์. ๐ซ
{ "user_id": 1, "activities": [ ... ์์ฒ ๊ฐ ... ] }๋ฌธ์ ํฌ๊ธฐ 16MB ์ ํ์ ๊ฑธ๋ฆฌ๊ณ , ๋ฐฐ์ด ๋์ ์ถ๊ฐํ ๋๋ง๋ค ์ ์ฒด ๋ฌธ์๋ฅผ ๋ค์ ์จ์ผ ํด.
ํด๊ฒฐ: ๋ฒํท ํจํด์ด๋ ๋ณ๋ ์ปฌ๋ ์ ์ผ๋ก ๋ถ๋ฆฌ!
์ฌ์ฉ์๋ง๋ค ๋ณ๋ ์ปฌ๋ ์ ์ ๋ง๋๋ ๊ฒฝ์ฐ (user_1_orders, user_2_orders...)
๋ค์์คํ์ด์ค ์ ํ์ ๊ฑธ๋ฆฌ๊ณ , ๊ด๋ฆฌ๊ฐ ๋ถ๊ฐ๋ฅํด์ ธ.
ํด๊ฒฐ: ํ๋์ ์ปฌ๋ ์ ์ user_id ํ๋๋ก ๊ตฌ๋ถ!
"ํน์ ๋ชฐ๋ผ์" ๋ชจ๋ ํ๋์ ์ธ๋ฑ์ค๋ฅผ ๊ฑฐ๋ ๊ฒฝ์ฐ.
์ฐ๊ธฐ ์ฑ๋ฅ์ด ํฌ๊ฒ ๋จ์ด์ง๊ณ , ๋์คํฌ ๊ณต๊ฐ๋ ๋ญ๋น๋ผ.
ํด๊ฒฐ: ์ค์ ์ฟผ๋ฆฌ ํจํด์ ๋ถ์ํด์ ํ์ํ ์ธ๋ฑ์ค๋ง ์์ฑ!
๋ชจ๋ ๊ฒ์ ์ ๊ทํํ๊ณ JOIN์ผ๋ก ์ฐ๊ฒฐํ๋ ค๋ ์๋.
MongoDB์ ๊ฐ์ ์ ์ ํ ์ด๋ฆฌ์ง ๋ชปํด.
ํด๊ฒฐ: ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฝ๊ธฐ ํจํด์ ์ค์ฌ์ผ๋ก ์ฌ์ค๊ณ!
{ "user_id": "507f1f77bcf86cd799439011" } (๋ฌธ์์ด)์ธ๋ฑ์ค ํจ์จ์ด ๋จ์ด์ง๊ณ , ์ ์ฅ ๊ณต๊ฐ๋ ๋ ์ฐจ์งํด.
ํด๊ฒฐ: ObjectId ํ์ ๊ทธ๋๋ก ์ฌ์ฉ!
๐ ์ธ๋ฑ์ค ์ ๋ต๊ณผ ์ฟผ๋ฆฌ ์ต์ ํ
์คํค๋ง ์ค๊ณ๊ฐ ๋๋ฌ๋ค๋ฉด, ์ด์ ์ธ๋ฑ์ค ์ ๋ต์ ์ธ์ธ ์ฐจ๋ก์ผ.
์๋ฌด๋ฆฌ ์ ์ค๊ณ๋ ์คํค๋ง๋ผ๋ ์ธ๋ฑ์ค๊ฐ ์์ผ๋ฉด ์ฑ๋ฅ์ด ํํธ์๊ฑฐ๋ ! ๐
๐ ์ธ๋ฑ์ค ๊ธฐ๋ณธ ์์น
MongoDB์ ์ธ๋ฑ์ค๋ B-Tree ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํด.
๊ด๊ณํ DB์ ๋น์ทํ์ง๋ง, ๋ช ๊ฐ์ง MongoDB๋ง์ ํน์ง์ด ์์ด.
// ๋จ์ผ ํ๋ ์ธ๋ฑ์ค
db.users.createIndex({ email: 1 }) // ์ค๋ฆ์ฐจ์
db.users.createIndex({ created_at: -1 }) // ๋ด๋ฆผ์ฐจ์
// ๋ณตํฉ ์ธ๋ฑ์ค (Compound Index)
db.orders.createIndex({ user_id: 1, order_date: -1 })
// ๊ณ ์ ์ธ๋ฑ์ค (Unique Index)
db.users.createIndex({ email: 1 }, { unique: true })
// ๋ถ๋ถ ์ธ๋ฑ์ค (Partial Index) - ์กฐ๊ฑด์ ๋ง๋ ๋ฌธ์๋ง ์ธ๋ฑ์ฑ
db.orders.createIndex(
{ status: 1 },
{ partialFilterExpression: { amount: { $gt: 10000 } } }
)
// TTL ์ธ๋ฑ์ค - ์ผ์ ์๊ฐ ํ ์๋ ์ญ์
db.sessions.createIndex(
{ created_at: 1 },
{ expireAfterSeconds: 3600 } // 1์๊ฐ ํ ์ญ์
)
1์์: ๊ณ ์ ์ฑ ์ ์ฝ์ด ํ์ํ ํ๋
์ด๋ฉ์ผ, ์ฌ์ฉ์๋ช ๋ฑ โ Unique Index
2์์: WHERE ์ ์ ์์ฃผ ์ฌ์ฉ๋๋ ํ๋
user_id, status, category ๋ฑ
3์์: ์ ๋ ฌ(ORDER BY)์ ์ฌ์ฉ๋๋ ํ๋
created_at, updated_at ๋ฑ
4์์: ๋ฒ์ ์ฟผ๋ฆฌ์ ์ฌ์ฉ๋๋ ํ๋
price, date ๋ฑ
๐จ ๋ณตํฉ ์ธ๋ฑ์ค ์ค๊ณ์ ์์
๋ณตํฉ ์ธ๋ฑ์ค๋ ํ๋ ์์๊ฐ ์ ๋ง ์ค์ํด!
ESR ๊ท์น์ ๊ธฐ์ตํ๋ฉด ์ฌ์. ๐
E (Equality): ๋๋ฑ ๋น๊ต ํ๋๋ฅผ ๋จผ์
{ status: "active" }S (Sort): ์ ๋ ฌ ํ๋๋ฅผ ๋ ๋ฒ์งธ
sort({ created_at: -1 })R (Range): ๋ฒ์ ์กฐ๊ฑด ํ๋๋ฅผ ๋ง์ง๋ง
{ price: { $gte: 10000, $lte: 50000 } }์ต์ ์ธ๋ฑ์ค:
db.products.createIndex({ status: 1, created_at: -1, price: 1 })
// ์ฟผ๋ฆฌ ์์
db.products.find({
status: "active",
price: { $gte: 10000, $lte: 50000 }
}).sort({ created_at: -1 })
// ์๋ชป๋ ์ธ๋ฑ์ค (๋นํจ์จ์ )
db.products.createIndex({ price: 1, status: 1, created_at: -1 })
// Range ํ๋๊ฐ ์์ ์ค๋ฉด ๋ค์ ํ๋๋ค์ ์ ๋๋ก ํ์ฉ ๋ชปํจ!
// ์ฌ๋ฐ๋ฅธ ์ธ๋ฑ์ค
db.products.createIndex({ status: 1, created_at: -1, price: 1 })
๐ ์ฟผ๋ฆฌ ์ฑ๋ฅ ๋ถ์
์ธ๋ฑ์ค๋ฅผ ๋ง๋ค์๋ค๋ฉด, ์ค์ ๋ก ์ ์ฌ์ฉ๋๋์ง ํ์ธํด์ผ ํด.
explain() ๋ฉ์๋๊ฐ ์ต๊ณ ์ ์น๊ตฌ์ผ! ๐
// ์คํ ๊ณํ ํ์ธ
db.orders.find({ user_id: ObjectId("...") })
.sort({ order_date: -1 })
.explain("executionStats")
// ์ฃผ์ ํ์ธ ์ฌํญ
{
"executionStats": {
"executionTimeMillis": 5, // ์คํ ์๊ฐ (๋ฎ์์๋ก ์ข์)
"totalDocsExamined": 10, // ๊ฒ์ฌํ ๋ฌธ์ ์
"totalKeysExamined": 10, // ๊ฒ์ฌํ ์ธ๋ฑ์ค ํค ์
"nReturned": 10, // ๋ฐํ๋ ๋ฌธ์ ์
"executionStages": {
"stage": "FETCH",
"inputStage": {
"stage": "IXSCAN", // ์ธ๋ฑ์ค ์ค์บ (์ข์!)
"indexName": "user_id_1_order_date_-1"
}
}
}
}
COLLSCAN: ์ปฌ๋ ์ ์ ์ฒด ์ค์บ โ ๋์จ! ์ธ๋ฑ์ค ํ์
IXSCAN: ์ธ๋ฑ์ค ์ค์บ โ ์ข์!
FETCH: ์ธ๋ฑ์ค๋ก ์ฐพ์ ํ ๋ฌธ์ ๊ฐ์ ธ์ค๊ธฐ โ ์ ์
์ด์์ ์ธ ๋น์จ:
totalKeysExamined โ nReturned (์ธ๋ฑ์ค ํจ์จ 100%)
totalDocsExamined โ nReturned (๋ถํ์ํ ๋ฌธ์ ๊ฒ์ฌ ์์)
๐ช ์ปค๋ฒ๋ง ์ธ๋ฑ์ค (Covered Query)
์ธ๋ฑ์ค๋ง์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ ํ ์ฒ๋ฆฌํ ์ ์๋ค๋ฉด, ๋ฌธ์๋ฅผ ์ฝ์ ํ์๊ฐ ์์ด์ ธ์ ์์ฒญ ๋นจ๋ผ! โก
์ด๊ฑธ ์ปค๋ฒ๋ง ์ธ๋ฑ์ค๋ผ๊ณ ํด.
// ์ธ๋ฑ์ค ์์ฑ
db.users.createIndex({ email: 1, name: 1, status: 1 })
// ์ปค๋ฒ๋ง ์ฟผ๋ฆฌ (์ธ๋ฑ์ค๋ง์ผ๋ก ์ฒ๋ฆฌ ๊ฐ๋ฅ)
db.users.find(
{ status: "active" },
{ email: 1, name: 1, status: 1, _id: 0 } // _id: 0 ์ค์!
)
// explain ๊ฒฐ๊ณผ์์ ํ์ธ
{
"executionStats": {
"totalDocsExamined": 0, // ๋ฌธ์๋ฅผ ํ๋๋ ์ ์ฝ์!
"executionStages": {
"stage": "PROJECTION_COVERED", // ์ปค๋ฒ๋ง!
"inputStage": {
"stage": "IXSCAN"
}
}
}
}
์ฃผ์ํ ์ ์ _id ํ๋๋ฅผ ์ ์ธํด์ผ ํ๋ค๋ ๊ฑฐ์ผ.
_id๋ ๊ธฐ๋ณธ์ ์ผ๋ก ํฌํจ๋๋๋ฐ, ์ธ๋ฑ์ค์ ์์ผ๋ฉด ๋ฌธ์๋ฅผ ์ฝ์ด์ผ ํ๊ฑฐ๋ !
โ๏ธ ์ปฌ๋ ์ ์ค๋ฉ๊ณผ ๋์ฉ๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
๋ฐ์ดํฐ๊ฐ ์ ๋ง ๋ง์์ง๋ฉด (์์ต ๊ฑด ์ด์), ๋จ์ผ ์๋ฒ๋ก๋ ํ๊ณ๊ฐ ์.
์ด๋ ํ์ํ ๊ฒ ์ค๋ฉ(Sharding)์ด์ผ! ๐
๐๏ธ ์ค๋ฉ์ด๋?
์ค๋ฉ์ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฌ ์๋ฒ(์ค๋)์ ์ํ ๋ถํ ํ๋ ๊ธฐ์ ์ด์ผ.
๊ฐ ์ค๋๋ ์ ์ฒด ๋ฐ์ดํฐ์ ์ผ๋ถ๋ง ์ ์ฅํ๊ณ , MongoDB๊ฐ ์๋์ผ๋ก ์ ์ ํ ์ค๋๋ก ์ฟผ๋ฆฌ๋ฅผ ๋ผ์ฐํ
ํด์ค.
๐ ์ค๋ ํค ์ ํ
์ค๋ฉ์์ ๊ฐ์ฅ ์ค์ํ ๊ฒฐ์ ์ด ์ค๋ ํค(Shard Key) ์ ํ์ด์ผ.
์ค๋ ํค๋ ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ๋ถ์ฐ์ํฌ์ง ๊ฒฐ์ ํ๋ ๊ธฐ์ค์ด๊ฑฐ๋ .
1. ๋์ ์นด๋๋๋ฆฌํฐ (Cardinality): ๊ณ ์ ํ ๊ฐ์ด ๋ง์์ผ ํด
โ ๋์จ: status (active/inactive ๋ ๊ฐ์ง๋ฟ)
โ ์ข์: user_id (์๋ฐฑ๋ง ๊ฐ์ ๊ณ ์ ๊ฐ)
2. ๊ท ๋ฑํ ๋ถ์ฐ: ๋ฐ์ดํฐ๊ฐ ํน์ ์ค๋์ ๋ชฐ๋ฆฌ์ง ์์์ผ ํด
โ ๋์จ: created_at (์ต๊ทผ ๋ฐ์ดํฐ๊ฐ ํ ์ค๋์ ์ง์ค)
โ ์ข์: hashed(user_id) (ํด์๋ก ๊ท ๋ฑ ๋ถ์ฐ)
3. ์ฟผ๋ฆฌ ํจํด๊ณผ ์ผ์น: ์์ฃผ ์ฌ์ฉํ๋ ํํฐ ์กฐ๊ฑด์ด์ด์ผ ํด
โ ์ข์: ๋๋ถ๋ถ์ ์ฟผ๋ฆฌ๊ฐ user_id๋ก ํํฐ๋งํ๋ค๋ฉด user_id๋ฅผ ์ค๋ ํค๋ก
// ์ค๋ฉ ํ์ฑํ
sh.enableSharding("mydb")
// ํด์ ์ค๋ ํค (๊ท ๋ฑ ๋ถ์ฐ์ ์ ๋ฆฌ)
sh.shardCollection("mydb.users", { user_id: "hashed" })
// ๋ฒ์ ์ค๋ ํค (๋ฒ์ ์ฟผ๋ฆฌ์ ์ ๋ฆฌ)
sh.shardCollection("mydb.orders", { user_id: 1, order_date: 1 })
// ๋ณตํฉ ์ค๋ ํค
sh.shardCollection("mydb.logs", {
app_id: 1,
timestamp: 1
})
ํ ๋ฒ ์ ํ๋ฉด ๋ณ๊ฒฝ ๋ถ๊ฐ! (MongoDB 5.0 ์ด์ )
MongoDB 5.0๋ถํฐ๋ resharding์ด ๊ฐ๋ฅํ์ง๋ง, ์์ฒญ๋ ๋น์ฉ์ด ๋ค์ด.
๋จ์กฐ ์ฆ๊ฐํ๋ ํค๋ ํผํด:
ObjectId, ํ์์คํฌํ ๊ฐ์ ๊ฐ์ ์ต์ ๋ฐ์ดํฐ๊ฐ ํ ์ค๋์ ๋ชฐ๋ ค.
ํด์ ์ค๋ ํค๋ฅผ ๊ณ ๋ คํด๋ด!
์ฟผ๋ฆฌ์ ์ค๋ ํค ํฌํจ:
์ค๋ ํค๊ฐ ์๋ ์ฟผ๋ฆฌ๋ ๋ชจ๋ ์ค๋๋ฅผ ๋ค์ ธ์ผ ํด์ ๋๋ ค.
๐ ์ฒญํฌ์ ๋ฐธ๋ฐ์ฑ
MongoDB๋ ๋ฐ์ดํฐ๋ฅผ ์ฒญํฌ(Chunk)๋ผ๋ ๋จ์๋ก ๋๋ ์ ๊ด๋ฆฌํด.
๊ธฐ๋ณธ์ ์ผ๋ก ์ฒญํฌ ํฌ๊ธฐ๋ 64MB์ด๊ณ , ์ฒญํฌ๊ฐ ๋๋ฌด ์ปค์ง๋ฉด ์๋์ผ๋ก ๋ถํ ๋ผ.
๊ทธ๋ฆฌ๊ณ ๋ฐธ๋ฐ์(Balancer)๊ฐ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์ฒญํฌ๋ฅผ ์ค๋ ๊ฐ์ ์ด๋์์ผ์
๋ฐ์ดํฐ๊ฐ ๊ท ๋ฑํ๊ฒ ๋ถ์ฐ๋๋๋ก ๊ด๋ฆฌํด์ค. ์์ ์๋์ด์ผ! ๐ค
๋ฐธ๋ฐ์ฑ์ I/O๋ฅผ ๋ง์ด ์ฌ์ฉํด์ ์๋น์ค์ ์ํฅ์ ์ค ์ ์์ด.
ํธ๋ํฝ์ด ์ ์ ์๊ฐ๋์๋ง ๋ฐธ๋ฐ์ฑํ๋๋ก ์ค์ ํ๋ ๊ฒ ์ข์!
sh.setBalancerState(true)db.settings.update( { _id: "balancer" },{ $set: { activeWindow: { start: "01:00", stop: "05:00" } } })
๐ ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง๊ณผ ํ๋
์คํค๋ง ์ค๊ณ์ ์ธ๋ฑ์ค ์ต์ ํ๊ฐ ๋๋ฌ๋ค๋ฉด, ์ด์ ์ง์์ ์ธ ๋ชจ๋ํฐ๋ง์ด ํ์ํด.
์๊ฐ์ด ์ง๋๋ฉด์ ๋ฐ์ดํฐ ํจํด์ด ๋ฐ๋๊ณ , ์๋ก์ด ๋ณ๋ชฉ์ด ์๊ธฐ๊ฑฐ๋ ! ๐
๐ ์ฃผ์ ๋ชจ๋ํฐ๋ง ์งํ
db.currentOp() - ํ์ฌ ์คํ ์ค์ธ ์ฟผ๋ฆฌ ํ์ธdb.system.profile.find() - ๋๋ฆฐ ์ฟผ๋ฆฌ ๋ก๊ทธ ๋ถ์๋๋ฆฐ ์ฟผ๋ฆฌ(100ms ์ด์)๋ฅผ ์ฐพ์์ ์ธ๋ฑ์ค ์ถ๊ฐ๋ ์ฟผ๋ฆฌ ๊ฐ์ ์ ํด์ผ ํด.
// ํ๋กํ์ผ๋ง ํ์ฑํ (๋ ๋ฒจ 1: 100ms ์ด์ ์ฟผ๋ฆฌ๋ง ๊ธฐ๋ก)
db.setProfilingLevel(1, { slowms: 100 })
// ๋๋ฆฐ ์ฟผ๋ฆฌ ํ์ธ
db.system.profile.find({
millis: { $gt: 100 }
}).sort({ ts: -1 }).limit(10).pretty()
// ํน์ ์ปฌ๋ ์
์ ๋๋ฆฐ ์ฟผ๋ฆฌ
db.system.profile.find({
ns: "mydb.users",
millis: { $gt: 100 }
})
๋ง๋ค์ด๋ ์ธ๋ฑ์ค๊ฐ ์ค์ ๋ก ์ฌ์ฉ๋๋์ง ํ์ธํด์ผ ํด.
์ฌ์ฉ๋์ง ์๋ ์ธ๋ฑ์ค๋ ์ฐ๊ธฐ ์ฑ๋ฅ๋ง ๋จ์ด๋จ๋ฆฌ๋๊น ์ญ์ ํ๋ ๊ฒ ์ข์!
// ์ธ๋ฑ์ค ์ฌ์ฉ ํต๊ณ
db.users.aggregate([
{ $indexStats: {} }
])
// ๊ฒฐ๊ณผ ์์
{
"name": "email_1",
"key": { "email": 1 },
"host": "server1:27017",
"accesses": {
"ops": 15234, // ์ฌ์ฉ ํ์
"since": ISODate("2024-01-01T00:00:00Z")
}
}
// ์ฌ์ฉ๋์ง ์๋ ์ธ๋ฑ์ค ์ฐพ๊ธฐ
db.users.aggregate([
{ $indexStats: {} },
{ $match: { "accesses.ops": 0 } }
])
MongoDB๋ ๊ฐ๋ฅํ ํ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์บ์ฑํด.
Working Set(์์ฃผ ์ ๊ทผํ๋ ๋ฐ์ดํฐ)์ด ๋ฉ๋ชจ๋ฆฌ์ ๋ค์ด๊ฐ์ผ ์ฑ๋ฅ์ด ์ข์!
// ์๋ฒ ์ํ ํ์ธ
db.serverStatus()
// ์ฃผ์ ๋ฉ๋ชจ๋ฆฌ ์งํ
{
"mem": {
"resident": 2048, // ์ค์ ์ฌ์ฉ ์ค์ธ ๋ฉ๋ชจ๋ฆฌ (MB)
"virtual": 4096, // ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ
"mapped": 3072 // ๋งคํ๋ ๋ฉ๋ชจ๋ฆฌ
},
"wiredTiger": {
"cache": {
"bytes currently in the cache": 1073741824, // 1GB
"maximum bytes configured": 2147483648, // 2GB
"pages evicted": 1234 // ์บ์์์ ์ ๊ฑฐ๋ ํ์ด์ง (๋ฎ์์๋ก ์ข์)
}
}
}
pages evicted ๊ฐ์ด ๊ณ์ ์ฆ๊ฐํ๋ค๋ฉด ๋ฉ๋ชจ๋ฆฌ๊ฐ ๋ถ์กฑํ๋ค๋ ์ ํธ์ผ.
์บ์ ํฌ๊ธฐ๋ฅผ ๋๋ฆฌ๊ฑฐ๋, ์๋ฒ๋ฅผ ์ฆ์คํด์ผ ํด! ๐ช
๋์ ์ฐ๊ฒฐ ์๊ฐ ๋๋ฌด ๋ง์ผ๋ฉด ์ฑ๋ฅ์ด ๋จ์ด์ ธ.
์ปค๋ฅ์ ํ๋ง์ ์ ๋๋ก ์ค์ ํ๋์ง ํ์ธํด๋ด.
// ํ์ฌ ์ฐ๊ฒฐ ์ ํ์ธ
db.serverStatus().connections
{
"current": 52, // ํ์ฌ ์ฐ๊ฒฐ ์
"available": 838808, // ์ฌ์ฉ ๊ฐ๋ฅํ ์ฐ๊ฒฐ ์
"totalCreated": 1234 // ์์ฑ๋ ์ด ์ฐ๊ฒฐ ์
}
// ์ฐ๊ฒฐ๋ณ ์ํ ํ์ธ
db.currentOp(true)
๐ ๏ธ ์ค์ ํ๋ ํ
1. ์ ์ ํ ์ธ๋ฑ์ค ์์ฑ
์์ฃผ ์ฌ์ฉํ๋ ์ฟผ๋ฆฌ ํจํด์ ๋ถ์ํด์ ๋ณตํฉ ์ธ๋ฑ์ค ์์ฑ
2. ์ปค๋ฒ๋ง ์ธ๋ฑ์ค ํ์ฉ
ํ์ํ ํ๋๋ง projectionํ๊ณ , _id ์ ์ธ
3. Read Preference ์ค์
์ฝ๊ธฐ ์ ์ฉ ์ฟผ๋ฆฌ๋ Secondary์์ ์ฝ๋๋ก ์ค์
4. ์ ์ ํ ๋ฐฐ์น ํฌ๊ธฐ
cursor.batchSize()๋ก ํ ๋ฒ์ ๊ฐ์ ธ์ฌ ๋ฌธ์ ์ ์กฐ์
1. ๋ถํ์ํ ์ธ๋ฑ์ค ์ ๊ฑฐ
์ธ๋ฑ์ค๊ฐ ๋ง์์๋ก ์ฐ๊ธฐ๊ฐ ๋๋ ค์ ธ
2. Write Concern ์กฐ์
์ค์ํ์ง ์์ ๋ก๊ทธ๋ w:0 ๋๋ w:1๋ก ์ค์
3. Bulk Write ์ฌ์ฉ
์ฌ๋ฌ ๋ฌธ์๋ฅผ ํ ๋ฒ์ ์ฐ๋ฉด ํจ์ฌ ๋นจ๋ผ
4. ๋ฌธ์ ํฌ๊ธฐ ์ต์ํ
๋ถํ์ํ ํ๋ ์ ๊ฑฐ, ์งง์ ํ๋๋ช ์ฌ์ฉ
// Bulk Write ์์
const bulk = db.users.initializeUnorderedBulkOp();
for (let i = 0; i < 10000; i++) {
bulk.insert({
name: `User ${i}`,
email: `user${i}@example.com`,
created_at: new Date()
});
}
bulk.execute(); // ํ ๋ฒ์ ์คํ!
// Write Concern ์ค์
db.logs.insertOne(
{ message: "User logged in", timestamp: new Date() },
{ writeConcern: { w: 0 } } // ํ์ธ ์ ๊ธฐ๋ค๋ฆผ (๋น ๋ฆ!)
)
๐ ๋ชจ๋ํฐ๋ง ๋๊ตฌ
MongoDB๋ฅผ ์ ๋๋ก ๋ชจ๋ํฐ๋งํ๋ ค๋ฉด ์ข์ ๋๊ตฌ๊ฐ ํ์ํด.
๋ฌด๋ฃ๋ถํฐ ์ ๋ฃ๊น์ง ๋ค์ํ ์ต์
์ด ์์ด! ๐ ๏ธ
1. MongoDB Atlas (๊ณต์, ํด๋ผ์ฐ๋)
MongoDB ๊ณต์ ํด๋ผ์ฐ๋ ์๋น์ค. ๋ชจ๋ํฐ๋ง, ๋ฐฑ์ , ์๋ฆผ ๋ชจ๋ ํฌํจ!
๋ฌด๋ฃ ํฐ์ด๋ ์์ด์ ํ ์คํธํ๊ธฐ ์ข์.
2. MongoDB Compass (๊ณต์, GUI)
์ฟผ๋ฆฌ ์ฑ๋ฅ ๋ถ์, ์ธ๋ฑ์ค ๊ด๋ฆฌ, ์คํค๋ง ์๊ฐํ ๋ฑ
๊ฐ๋ฐํ ๋ ์ ๋ง ์ ์ฉํด!
3. Percona Monitoring and Management (PMM)
์คํ์์ค ๋ชจ๋ํฐ๋ง ๋๊ตฌ. Grafana ๊ธฐ๋ฐ์ผ๋ก ์์ ๋์๋ณด๋ ์ ๊ณต
4. mongostat / mongotop (CLI)
๊ฐ๋จํ ์ค์๊ฐ ๋ชจ๋ํฐ๋ง์ ์ ์ฉ
mongostat --host localhost:27017mongotop --host localhost:27017
๐ ์ค์ ์ฌ๋ก: ์ฌ๋ฅ๋ท ์คํค๋ง ์ค๊ณ
์ด๋ก ์ ์ถฉ๋ถํ ๋ฐฐ์ ์ผ๋, ์ด์ ์ค์ ์ฌ๋ก๋ฅผ ๋ณด์!
์ฌ๋ฅ๋ท ๊ฐ์ ์ฌ๋ฅ ๊ณต์ ํ๋ซํผ์ ์คํค๋ง๋ฅผ ์ด๋ป๊ฒ ์ค๊ณํ ์ง ์๊ฐํด๋ณผ๊ฒ. ๐จ
๐ ์๊ตฌ์ฌํญ ๋ถ์
โข ์ฌ์ฉ์ (Users)
โข ์ฌ๋ฅ (Talents)
โข ์นดํ ๊ณ ๋ฆฌ (Categories)
โข ์ฃผ๋ฌธ/๊ฑฐ๋ (Orders)
โข ๋ฆฌ๋ทฐ (Reviews)
โข ๋ฉ์์ง (Messages)
โข ์นดํ ๊ณ ๋ฆฌ๋ณ ์ฌ๋ฅ ๋ชฉ๋ก ์กฐํ (์ฝ๊ธฐ ๋ง์)
โข ์ฌ์ฉ์์ ์ฌ๋ฅ ๋ชฉ๋ก ์กฐํ
โข ์ฃผ๋ฌธ ๋ด์ญ ์กฐํ (์ฌ์ฉ์๋ณ, ํ๋งค์๋ณ)
โข ์ฌ๋ฅ ์์ธ + ๋ฆฌ๋ทฐ ์กฐํ (ํจ๊ป ์กฐํ)
โข ์ค์๊ฐ ๋ฉ์์ง (์ฐ๊ธฐ ๋ง์)
๐๏ธ ์คํค๋ง ์ค๊ณ
// 1. Users ์ปฌ๋ ์
{
"_id": ObjectId("..."),
"email": "dev@example.com",
"name": "๊น๊ฐ๋ฐ",
"profile": {
"bio": "ํ์คํ ๊ฐ๋ฐ์์
๋๋ค",
"avatar": "https://...",
"skills": ["JavaScript", "MongoDB", "React"]
},
"stats": {
"total_sales": 1500000,
"total_orders": 42,
"rating": 4.8,
"review_count": 38
},
"created_at": ISODate("2023-01-15"),
"updated_at": ISODate("2024-01-20")
}
// ์ธ๋ฑ์ค
db.users.createIndex({ email: 1 }, { unique: true })
db.users.createIndex({ "stats.rating": -1 }) // ์ธ๊ธฐ ํ๋งค์ ์กฐํ
์ฌ์ฉ์ ํต๊ณ(stats)๋ ์๋ฒ ๋๋๋ก ์ ์ฅํ์ด.
ํ๋กํ ์กฐํํ ๋ ํญ์ ํจ๊ป ๋ณด์ฌ์ฃผ๋๊น ํ ๋ฒ์ ๊ฐ์ ธ์ค๋ ๊ฒ ํจ์จ์ ์ด์ง!
// 2. Talents ์ปฌ๋ ์
{
"_id": ObjectId("..."),
"seller_id": ObjectId("..."),
"seller_name": "๊น๊ฐ๋ฐ", // ์ค๋
์ท (Extended Reference)
"seller_avatar": "https://...",
"title": "MongoDB ์คํค๋ง ์ค๊ณ ์ปจ์คํ
",
"description": "...",
"category": {
"id": ObjectId("..."),
"name": "IT/ํ๋ก๊ทธ๋๋ฐ",
"path": ["IT/ํ๋ก๊ทธ๋๋ฐ", "๋ฐ์ดํฐ๋ฒ ์ด์ค", "MongoDB"] // ๊ณ์ธต ๊ตฌ์กฐ
},
"price": 50000,
"delivery_days": 7,
"tags": ["MongoDB", "์คํค๋ง์ค๊ณ", "DB์ต์ ํ"],
"stats": {
"views": 1234,
"orders": 42,
"rating": 4.8,
"review_count": 38
},
"status": "active", // active, paused, deleted
"created_at": ISODate("2023-06-01"),
"updated_at": ISODate("2024-01-15")
}
// ์ธ๋ฑ์ค
db.talents.createIndex({ seller_id: 1, status: 1 })
db.talents.createIndex({ "category.id": 1, status: 1, "stats.rating": -1 })
db.talents.createIndex({ status: 1, created_at: -1 }) // ์ต์ ์
db.talents.createIndex({ tags: 1 }) // ํ๊ทธ ๊ฒ์
db.talents.createIndex({
title: "text",
description: "text",
tags: "text"
}) // ์ ๋ฌธ ๊ฒ์
์ฌ๋ฅ ๋ฌธ์์ ํ๋งค์ ์ด๋ฆ๊ณผ ์๋ฐํ๋ฅผ ์ค๋
์ท์ผ๋ก ์ ์ฅํ์ด.
๋ชฉ๋ก ์กฐํํ ๋ ํ๋งค์ ์ ๋ณด๋ฅผ ๋ณ๋๋ก ์กฐํํ์ง ์์๋ ๋๋๊น ๋น ๋ฅด์ง!
์นดํ
๊ณ ๋ฆฌ๋ ๊ฒฝ๋ก๋ฅผ ์ ์ฅํด์ "IT/ํ๋ก๊ทธ๋๋ฐ" ํ์ ๋ชจ๋ ์ฌ๋ฅ์ ์ฝ๊ฒ ์ฐพ์ ์ ์์ด.
// 3. Orders ์ปฌ๋ ์
{
"_id": ObjectId("..."),
"order_number": "ORD-2024-001234",
"buyer": {
"id": ObjectId("..."),
"name": "์ด๊ตฌ๋งค",
"email": "buyer@example.com"
},
"seller": {
"id": ObjectId("..."),
"name": "๊น๊ฐ๋ฐ",
"email": "seller@example.com"
},
"talent": {
"id": ObjectId("..."),
"title": "MongoDB ์คํค๋ง ์ค๊ณ ์ปจ์คํ
",
"price": 50000,
"delivery_days": 7
},
"amount": 50000,
"status": "completed", // pending, in_progress, completed, cancelled
"payment": {
"method": "card",
"paid_at": ISODate("2024-01-15T10:30:00Z"),
"transaction_id": "TXN123456"
},
"delivery": {
"started_at": ISODate("2024-01-15T11:00:00Z"),
"completed_at": ISODate("2024-01-20T15:30:00Z"),
"files": [
{ "name": "schema_design.pdf", "url": "https://..." }
]
},
"created_at": ISODate("2024-01-15T10:00:00Z"),
"updated_at": ISODate("2024-01-20T15:30:00Z")
}
// ์ธ๋ฑ์ค
db.orders.createIndex({ "buyer.id": 1, created_at: -1 })
db.orders.createIndex({ "seller.id": 1, created_at: -1 })
db.orders.createIndex({ status: 1, created_at: -1 })
db.orders.createIndex({ order_number: 1 }, { unique: true })
์ฃผ๋ฌธ ๋ฌธ์๋ ์ค๋
์ท ํจํด์ ์ ๊ทน ํ์ฉํ์ด.
์ฃผ๋ฌธ ๋น์์ ์ฌ๋ฅ ์ ๋ณด(๊ฐ๊ฒฉ, ์ ๋ชฉ ๋ฑ)๋ฅผ ์ ์ฅํด์,
๋์ค์ ์ฌ๋ฅ ์ ๋ณด๊ฐ ๋ฐ๋์ด๋ ์ฃผ๋ฌธ ๋ด์ญ์ ๊ทธ๋๋ก ์ ์ง๋ผ. ๐ธ
// 4. Reviews ์ปฌ๋ ์
{
"_id": ObjectId("..."),
"order_id": ObjectId("..."),
"talent_id": ObjectId("..."),
"buyer": {
"id": ObjectId("..."),
"name": "์ด๊ตฌ๋งค",
"avatar": "https://..."
},
"seller_id": ObjectId("..."),
"rating": 5,
"comment": "์ ๋ง ๋์์ด ๋ง์ด ๋์์ต๋๋ค!",
"images": [
"https://...",
"https://..."
],
"reply": { // ํ๋งค์ ๋ต๋ณ
"comment": "๊ฐ์ฌํฉ๋๋ค!",
"created_at": ISODate("2024-01-21T10:00:00Z")
},
"created_at": ISODate("2024-01-20T16:00:00Z")
}
// ์ธ๋ฑ์ค
db.reviews.createIndex({ talent_id: 1, created_at: -1 })
db.reviews.createIndex({ "buyer.id": 1, created_at: -1 })
db.reviews.createIndex({ seller_id: 1, created_at: -1 })
๋ฆฌ๋ทฐ๋ ๋ณ๋ ์ปฌ๋ ์
์ผ๋ก ๋ถ๋ฆฌํ์ด.
์ฌ๋ฅ ๋ฌธ์์ ์๋ฒ ๋๋ํ๋ฉด ๋ฆฌ๋ทฐ๊ฐ ๋ง์์ง์๋ก ๋ฌธ์๊ฐ ๋๋ฌด ์ปค์ง๊ฑฐ๋ !
๋์ ์ฌ๋ฅ ๋ฌธ์์๋ ํต๊ณ(ํ๊ท ํ์ , ๋ฆฌ๋ทฐ ์)๋ง ์ ์ฅํด๋ฌ.
// 5. Messages ์ปฌ๋ ์
(๋ฒํท ํจํด)
{
"_id": ObjectId("..."),
"conversation_id": "507f1f77bcf86cd799439011_507f191e810c19729de860ea",
"participants": [
ObjectId("507f1f77bcf86cd799439011"),
ObjectId("507f191e810c19729de860ea")
],
"start_time": ISODate("2024-01-15T10:00:00Z"),
"end_time": ISODate("2024-01-15T11:00:00Z"),
"messages": [
{
"sender_id": ObjectId("507f1f77bcf86cd799439011"),
"text": "์๋
ํ์ธ์!",
"timestamp": ISODate("2024-01-15T10:05:00Z"),
"read": true
},
{
"sender_id": ObjectId("507f191e810c19729de860ea"),
"text": "๋ค, ์๋
ํ์ธ์!",
"timestamp": ISODate("2024-01-15T10:06:00Z"),
"read": true
}
// ... ์ต๋ 100๊ฐ ๋ฉ์์ง
],
"message_count": 2
}
// ์ธ๋ฑ์ค
db.messages.createIndex({ conversation_id: 1, start_time: -1 })
db.messages.createIndex({ participants: 1, start_time: -1 })
๋ฉ์์ง๋ ๋ฒํท ํจํด์ ์ฌ์ฉํ์ด!
1์๊ฐ ๋๋ 100๊ฐ ๋ฉ์์ง ๋จ์๋ก ๋ฌถ์ด์ ์ ์ฅํ๋ฉด,
์๋ฐฑ๋ง ๊ฐ์ ๋ฉ์์ง๋ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ด. ๐ฌ
๐ฏ ์ฟผ๋ฆฌ ์์
// ์นดํ
๊ณ ๋ฆฌ๋ณ ์ธ๊ธฐ ์ฌ๋ฅ ์กฐํ
db.talents.find({
"category.id": ObjectId("..."),
status: "active"
}).sort({ "stats.rating": -1, "stats.orders": -1 }).limit(20)
// ์ฌ์ฉ์์ ์ฃผ๋ฌธ ๋ด์ญ ์กฐํ (๊ตฌ๋งค์)
db.orders.find({
"buyer.id": ObjectId("...")
}).sort({ created_at: -1 })
// ์ฌ๋ฅ ์์ธ + ์ต๊ทผ ๋ฆฌ๋ทฐ ์กฐํ
const talent = db.talents.findOne({ _id: ObjectId("...") })
const reviews = db.reviews.find({
talent_id: ObjectId("...")
}).sort({ created_at: -1 }).limit(10)
// ์ ๋ฌธ ๊ฒ์ (์ ๋ชฉ, ์ค๋ช
, ํ๊ทธ)
db.talents.find({
$text: { $search: "MongoDB ์คํค๋ง ์ค๊ณ" },
status: "active"
}).sort({ score: { $meta: "textScore" } })
// ๋ํ ๋ด์ญ ์กฐํ (์ต๊ทผ 10๊ฐ ๋ฒํท)
db.messages.find({
conversation_id: "..."
}).sort({ start_time: -1 }).limit(10)
1. ์ฝ๊ธฐ ์ต์ ํ: ์์ฃผ ํจ๊ป ์กฐํ๋๋ ๋ฐ์ดํฐ๋ ์๋ฒ ๋๋ ๋๋ ์ค๋ ์ท
2. ํ์ฅ์ฑ: ๋ฌดํ์ ์ปค์ง ์ ์๋ ๋ฐ์ดํฐ๋ ๋ณ๋ ์ปฌ๋ ์ ๋๋ ๋ฒํท ํจํด
3. ์ผ๊ด์ฑ: ์ฃผ๋ฌธ ๊ฐ์ ์ค์ ๋ฐ์ดํฐ๋ ์ค๋ ์ท์ผ๋ก ๋น์ ์ ๋ณด ๋ณด์กด
4. ๊ฒ์ ์ฑ๋ฅ: ์์ฃผ ์ฌ์ฉํ๋ ํํฐ์ ์ ๋ ฌ ์กฐ๊ฑด์ ๋ณตํฉ ์ธ๋ฑ์ค ์์ฑ
5. ์ ์ฐ์ฑ: ํฅํ ํ์ฅ์ ๊ณ ๋ คํ ๊ตฌ์กฐ (์: ์นดํ ๊ณ ๋ฆฌ ๊ฒฝ๋ก ๋ฐฐ์ด)
๐ฌ ๋ง๋ฌด๋ฆฌํ๋ฉฐ
์, ์ฌ๊ธฐ๊น์ง ์ ๋ง ๊ธด ์ฌ์ ์ด์์ด! ๐
MongoDB ์คํค๋ง ์ค๊ณ์ ์ปฌ๋ ์
์ต์ ํ์ ๋ํด ๋ง์ ๊ฑธ ๋ฐฐ์ ์ง?
ํต์ฌ์ ๋ค์ ํ๋ฒ ์ ๋ฆฌํด๋ณด์๋ฉด:
1. ์ ํ๋ฆฌ์ผ์ด์
์ ์ฝ๊ธฐ ํจํด์ ์ค์ฌ์ผ๋ก ์ค๊ณํ๋ผ
๊ด๊ณํ DB์ฒ๋ผ ์ ๊ทํ์ ์ง์ฐฉํ์ง ๋ง๊ณ , ํจ๊ป ์กฐํ๋๋ ๋ฐ์ดํฐ๋ ํจ๊ป ์ ์ฅํด.
2. ์๋ฒ ๋๋ vs ๋ ํผ๋ฐ์ค๋ฅผ ์ํฉ์ ๋ง๊ฒ ์ ํํ๋ผ
๋ฐ์ดํฐ ํฌ๊ธฐ, ์กฐํ ํจํด, ์
๋ฐ์ดํธ ๋น๋๋ฅผ ๊ณ ๋ คํด์ ๊ฒฐ์ ํด.
3. ๊ฒ์ฆ๋ ํจํด์ ํ์ฉํ๋ผ
Tree, Bucket, Extended Reference ๋ฑ ์ํฉ์ ๋ง๋ ํจํด์ ์ฌ์ฉํด.
4. ์ธ๋ฑ์ค๋ฅผ ์ ๋ต์ ์ผ๋ก ์์ฑํ๋ผ
ESR ๊ท์น์ ๋ฐ๋ฅด๊ณ , ์ฌ์ฉ๋์ง ์๋ ์ธ๋ฑ์ค๋ ๊ณผ๊ฐํ ์ ๊ฑฐํด.
5. ์ง์์ ์ผ๋ก ๋ชจ๋ํฐ๋งํ๊ณ ๊ฐ์ ํ๋ผ
๋๋ฆฐ ์ฟผ๋ฆฌ๋ฅผ ์ฐพ์์ ์ต์ ํํ๊ณ , ๋ฐ์ดํฐ ํจํด ๋ณํ์ ๋์ํด.
์ด์ ์ด๋ก ์ ์ถฉ๋ถํ ๋ฐฐ์ ์ผ๋, ์ง์ ์ค์ตํด๋ณด๋ ๊ฒ ์ค์ํด!
1. ์์ ํ๋ก์ ํธ๋ก ์์: ๊ฐ๋จํ ๋ธ๋ก๊ทธ๋ TODO ์ฑ์ผ๋ก ์ฐ์ต
2. explain() ์ต๊ดํ: ๋ชจ๋ ์ฟผ๋ฆฌ์ explain()์ ๋ถ์ฌ์ ์ฑ๋ฅ ํ์ธ
3. ์ค์ ๋ฐ์ดํฐ๋ก ํ ์คํธ: ์๋ง~์์ญ๋ง ๊ฑด์ ๋ฐ์ดํฐ๋ก ์ฑ๋ฅ ์ธก์
4. ์ปค๋ฎค๋ํฐ ํ์ฉ: MongoDB ๊ณต์ ํฌ๋ผ, Stack Overflow์์ ์ง๋ฌธํ๊ณ ๋ฐฐ์ฐ๊ธฐ
5. ๊ณต์ ๋ฌธ์ ์ฝ๊ธฐ: MongoDB ๊ณต์ ๋ฌธ์๋ ์ ๋ง ์ ๋์ด ์์ด!
์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์ ๋ง๋ค๋ , ๊ฐ์ธ ํ๋ก์ ํธ๋ฅผ ํ๋ ,
MongoDB ์คํค๋ง ์ค๊ณ๋ ์ฒ์๋ถํฐ ์ ๋๋ก ํ๋ ๊ฒ ์ ๋ง ์ค์ํด.
๋์ค์ ๋ง์ด๊ทธ๋ ์ด์
ํ๋ ค๋ฉด ์์ฒญ๋ ๊ณ ์์ ํ๊ฑฐ๋ ! ๐
์ด ๊ธ์ด MongoDB ์คํค๋ง ์ค๊ณ์ ๊ณ ๋ฏผํ๋ ๋ชจ๋ ๊ฐ๋ฐ์๋ค์๊ฒ ๋์์ด ๋๊ธธ ๋ฐ๋ผ!
๊ถ๊ธํ ์ ์ด ์์ผ๋ฉด ์ธ์ ๋ ์ฌ๋ฅ๋ท ์ปค๋ฎค๋ํฐ์์ ๋ฌผ์ด๋ด.
ํจ๊ป ์ฑ์ฅํ๋ ๊ฐ๋ฐ์๊ฐ ๋์! ๐ชโจ
MongoDB ๊ณต์ ๋ฌธ์: docs.mongodb.com
MongoDB University: learn.mongodb.com (๋ฌด๋ฃ ๊ฐ์!)
MongoDB Blog: ์ค์ ์ฌ๋ก์ ๋ฒ ์คํธ ํ๋ํฐ์ค
์ฌ๋ฅ๋ท ์ง์์ธ์ ์ฒ: ๋ ๋ง์ ๊ฐ๋ฐ ์ง์ ๊ณต์ !
Happy Coding! ๐จ๐ป๐
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.