์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ NoSQL์˜ ์–‘๋Œ€ ์‚ฐ๋งฅ! MongoDB์™€ Cassandra๋กœ ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ ์ •๋ณตํ•˜๊ธฐ

๐Ÿš€ NoSQL์˜ ์–‘๋Œ€ ์‚ฐ๋งฅ! MongoDB์™€ Cassandra๋กœ ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ ์ •๋ณตํ•˜๊ธฐ

์นœ๊ตฌ์ฒ˜๋Ÿผ ์‰ฝ๊ฒŒ ๋ฐฐ์šฐ๋Š” NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์™„์ „ ์ •๋ณต ๊ฐ€์ด๋“œ

## ๐ŸŽฏ ์™œ NoSQL์ด ํ•„์š”ํ• ๊นŒ? ์ „ํ†ต์ ์ธ DB์˜ ํ•œ๊ณ„๋ฅผ ๋„˜์–ด์„œ ์•ˆ๋…•! ์˜ค๋Š˜์€ ์ •๋ง ์žฌ๋ฏธ์žˆ๋Š” ์ฃผ์ œ๋กœ ์ด์•ผ๊ธฐํ•ด๋ณผ ๊ฑฐ์•ผ. ๋ฐ”๋กœ NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ธ๋ฐ, ํŠนํžˆ MongoDB์™€ Cassandra๋ผ๋Š” ๋‘ ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์— ๋Œ€ํ•ด ๊นŠ์ด ํŒŒํ—ค์ณ๋ณผ ๊ฑฐ์•ผ. ๐Ÿ˜Š

๋จผ์ € ์ด๋Ÿฐ ์ƒํ™ฉ์„ ์ƒ์ƒํ•ด๋ด. ๋„ˆ๊ฐ€ ๋งŒ๋“  ์•ฑ์ด ๊ฐ‘์ž๊ธฐ ๋Œ€๋ฐ•์ด ๋‚ฌ์–ด! ์‚ฌ์šฉ์ž๊ฐ€ ํ•˜๋ฃจ์— 10๋ช…์—์„œ 100๋งŒ ๋ช…์œผ๋กœ ํญ๋ฐœ์ ์œผ๋กœ ๋Š˜์–ด๋‚ฌ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ด. ๊ธฐ์กด์— ์‚ฌ์šฉํ•˜๋˜ MySQL์ด๋‚˜ PostgreSQL ๊ฐ™์€ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(RDBMS)๋Š” ์ˆจ์ด ํ„ฑํ„ฑ ๋ง‰ํžˆ๊ธฐ ์‹œ์ž‘ํ•  ๊ฑฐ์•ผ. ์™œ ๊ทธ๋Ÿด๊นŒ?

์ „ํ†ต์ ์ธ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ACID ์†์„ฑ(Atomicity, Consistency, Isolation, Durability)์„ ์—„๊ฒฉํ•˜๊ฒŒ ์ง€ํ‚ค๋ฉด์„œ ๋ฐ์ดํ„ฐ์˜ ์ •ํ•ฉ์„ฑ์„ ๋ณด์žฅํ•ด. ์ด๊ฑด ์ •๋ง ํ›Œ๋ฅญํ•œ ํŠน์„ฑ์ด์ง€๋งŒ, ๋Œ€๊ทœ๋ชจ ํŠธ๋ž˜ํ”ฝ๊ณผ ๋น…๋ฐ์ดํ„ฐ ํ™˜๊ฒฝ์—์„œ๋Š” ๋ณ‘๋ชฉํ˜„์ƒ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์–ด. ํŠนํžˆ ์ˆ˜ํ‰์  ํ™•์žฅ(Scale-out)์ด ์–ด๋ ต๋‹ค๋Š” ๊ฒŒ ํฐ ๋ฌธ์ œ์•ผ.

๐Ÿ’ก ์ž ๊น! RDBMS์˜ ํ•œ๊ณ„์  โ€ข ์ˆ˜์ง์  ํ™•์žฅ(Scale-up)์— ์˜์กด: ์„œ๋ฒ„ ์„ฑ๋Šฅ์„ ๋†’์ด๋Š” ๋ฐ ํ•œ๊ณ„๊ฐ€ ์žˆ๊ณ  ๋น„์šฉ์ด ๊ธฐํ•˜๊ธ‰์ˆ˜์ ์œผ๋กœ ์ฆ๊ฐ€
โ€ข ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ์˜ ์–ด๋ ค์›€: ํ…Œ์ด๋ธ” ๊ตฌ์กฐ๋ฅผ ๋ฐ”๊พธ๋ ค๋ฉด ์ „์ฒด ์‹œ์Šคํ…œ์— ์˜ํ–ฅ
โ€ข ์กฐ์ธ ์—ฐ์‚ฐ์˜ ๋ถ€๋‹ด: ๋ณต์žกํ•œ ๊ด€๊ณ„๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ์„ฑ๋Šฅ ์ €ํ•˜
โ€ข ๋ถ„์‚ฐ ํ™˜๊ฒฝ์—์„œ์˜ ๋ณต์žก์„ฑ: ์—ฌ๋Ÿฌ ์„œ๋ฒ„์— ๋ฐ์ดํ„ฐ๋ฅผ ๋‚˜๋ˆ„๊ธฐ ์–ด๋ ค์›€
์ด๋Ÿฐ ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ•œ ๊ฒŒ ๋ฐ”๋กœ NoSQL์ด์•ผ! "Not Only SQL"์˜ ์•ฝ์ž๋กœ, SQL๋งŒ์ด ์•„๋‹Œ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๊ฒ ๋‹ค๋Š” ์ฒ ํ•™์„ ๋‹ด๊ณ  ์žˆ์–ด. ๐ŸŽจ
NoSQL์˜ ์ง„ํ™” RDBMS ์ˆ˜์ง์  ํ™•์žฅ ์—„๊ฒฉํ•œ ์Šคํ‚ค๋งˆ ์ง„ํ™” MongoDB ๋ฌธ์„œ ์ง€ํ–ฅ / ์œ ์—ฐํ•œ ์Šคํ‚ค๋งˆ Cassandra ์ปฌ๋Ÿผ ํŒจ๋ฐ€๋ฆฌ / ์ดˆ๊ณ ์† ์“ฐ๊ธฐ ์ˆ˜ํ‰์  ํ™•์žฅ ๋ถ„์‚ฐ ์ฒ˜๋ฆฌ ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ โœ“ ๋น ๋ฅธ ์ฝ๊ธฐ/์“ฐ๊ธฐ โœ“ ์œ ์—ฐํ•œ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ โœ“ ๊ณ ๊ฐ€์šฉ์„ฑ โœ“ ์ž๋™ ์ƒค๋”ฉ โœ“ ์‹ค์‹œ๊ฐ„ ๋ถ„์„ ๋ฐ์ดํ„ฐ ์ฆ๊ฐ€ ์ถ”์„ธ
## ๐Ÿ“š NoSQL์˜ 4๊ฐ€์ง€ ์ฃผ์š” ์œ ํ˜• ์ดํ•ดํ•˜๊ธฐ NoSQL์€ ํฌ๊ฒŒ 4๊ฐ€์ง€ ์œ ํ˜•์œผ๋กœ ๋‚˜๋‰˜์–ด. ๊ฐ๊ฐ์˜ ํŠน์ง•์„ ์•Œ์•„๋‘๋ฉด ์–ด๋–ค ์ƒํ™ฉ์—์„œ ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์„ ํƒํ•ด์•ผ ํ• ์ง€ ํŒ๋‹จํ•˜๊ธฐ ์‰ฌ์›Œ์ ธ! ๐Ÿค”

1๏ธโƒฃ ๋ฌธ์„œ ์ง€ํ–ฅ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค (Document Store) ๋Œ€ํ‘œ์ฃผ์ž: MongoDB, CouchDB

JSON์ด๋‚˜ BSON ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด. ๋งˆ์น˜ ์›Œ๋“œ ๋ฌธ์„œ์ฒ˜๋Ÿผ ํ•˜๋‚˜์˜ ๋ฌธ์„œ ์•ˆ์— ๊ด€๋ จ๋œ ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ์–ด์„œ ์ง๊ด€์ ์ด์•ผ. ์Šคํ‚ค๋งˆ๊ฐ€ ์œ ์—ฐํ•ด์„œ ํ•„๋“œ๋ฅผ ์ž์œ ๋กญ๊ฒŒ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒŒ ์ตœ๊ณ ์˜ ์žฅ์ ์ด์ง€! ๐Ÿ“„

์ ํ•ฉํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€: ์ฝ˜ํ…์ธ  ๊ด€๋ฆฌ ์‹œ์Šคํ…œ, ์ „์ž์ƒ๊ฑฐ๋ž˜ ์นดํƒˆ๋กœ๊ทธ, ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ๊ด€๋ฆฌ
2๏ธโƒฃ ํ‚ค-๊ฐ’ ์ €์žฅ์†Œ (Key-Value Store) ๋Œ€ํ‘œ์ฃผ์ž: Redis, DynamoDB, Riak

๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ํ˜•ํƒœ์•ผ. ํ‚ค(Key)์™€ ๊ฐ’(Value)์˜ ์Œ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•ด. ๋งˆ์น˜ ์‚ฌ์ „์ฒ˜๋Ÿผ ๋‹จ์–ด(ํ‚ค)๋ฅผ ์ฐพ์œผ๋ฉด ๋œป(๊ฐ’)์ด ๋‚˜์˜ค๋Š” ๊ตฌ์กฐ์ง€. ์—„์ฒญ๋‚˜๊ฒŒ ๋น ๋ฅธ ์กฐํšŒ ์†๋„๊ฐ€ ํŠน์ง•์ด์•ผ! โšก

์ ํ•ฉํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€: ์„ธ์…˜ ๊ด€๋ฆฌ, ์บ์‹ฑ, ์‹ค์‹œ๊ฐ„ ์ถ”์ฒœ ์‹œ์Šคํ…œ
3๏ธโƒฃ ์ปฌ๋Ÿผ ํŒจ๋ฐ€๋ฆฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค (Column Family Store) ๋Œ€ํ‘œ์ฃผ์ž: Apache Cassandra, HBase

๋ฐ์ดํ„ฐ๋ฅผ ํ–‰์ด ์•„๋‹Œ ์—ด(์ปฌ๋Ÿผ) ๋‹จ์œ„๋กœ ์ €์žฅํ•ด. ๊ฐ™์€ ์ข…๋ฅ˜์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ์•„์„œ ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์••์ถ•๋ฅ ์ด ๋†’๊ณ , ํŠน์ • ์ปฌ๋Ÿผ๋งŒ ๋น ๋ฅด๊ฒŒ ์ฝ์„ ์ˆ˜ ์žˆ์–ด. ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ๋ถ„์„์— ์ตœ์ ํ™”๋˜์–ด ์žˆ์ง€! ๐Ÿ“Š

์ ํ•ฉํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€: ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ, ๋กœ๊ทธ ๋ถ„์„, IoT ์„ผ์„œ ๋ฐ์ดํ„ฐ
4๏ธโƒฃ ๊ทธ๋ž˜ํ”„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค (Graph Database) ๋Œ€ํ‘œ์ฃผ์ž: Neo4j, Amazon Neptune

๋ฐ์ดํ„ฐ ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๊ทธ๋ž˜ํ”„ ๊ตฌ์กฐ๋กœ ํ‘œํ˜„ํ•ด. ๋…ธ๋“œ(Node)์™€ ์—ฃ์ง€(Edge)๋กœ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์–ด์„œ ๋ณต์žกํ•œ ๊ด€๊ณ„๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๋ฐ ํƒ์›”ํ•ด. SNS์˜ ์นœ๊ตฌ ๊ด€๊ณ„๋‚˜ ์ถ”์ฒœ ์‹œ์Šคํ…œ์— ๋”ฑ์ด์•ผ! ๐Ÿ•ธ๏ธ

์ ํ•ฉํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€: ์†Œ์…œ ๋„คํŠธ์›Œํฌ, ์ถ”์ฒœ ์—”์ง„, ์‚ฌ๊ธฐ ํƒ์ง€ ์‹œ์Šคํ…œ
## ๐Ÿƒ MongoDB: ๊ฐœ๋ฐœ์ž๊ฐ€ ์‚ฌ๋ž‘ํ•˜๋Š” ๋ฌธ์„œ ์ง€ํ–ฅ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ MongoDB์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊นŒ? MongoDB๋Š” 2009๋…„์— ๋“ฑ์žฅํ•œ ์ดํ›„๋กœ ๊ฐœ๋ฐœ์ž๋“ค ์‚ฌ์ด์—์„œ ํญ๋ฐœ์ ์ธ ์ธ๊ธฐ๋ฅผ ์–ป์—ˆ์–ด. ๊ทธ ์ด์œ ๊ฐ€ ๋ญ˜๊นŒ? ๐Ÿคฉ

๐ŸŽจ MongoDB์˜ ํ•ต์‹ฌ ํŠน์ง•
1. ์œ ์—ฐํ•œ ์Šคํ‚ค๋งˆ (Flexible Schema)

MongoDB์˜ ๊ฐ€์žฅ ํฐ ๋งค๋ ฅ์€ ๋ฐ”๋กœ ์Šคํ‚ค๋งˆ๋ฆฌ์Šค(Schema-less) ๊ตฌ์กฐ์•ผ. ์ •ํ™•ํžˆ๋Š” "๋™์  ์Šคํ‚ค๋งˆ"๋ผ๊ณ  ํ‘œํ˜„ํ•˜๋Š” ๊ฒŒ ๋งž์•„. ๊ฐ™์€ ์ปฌ๋ ‰์…˜ ์•ˆ์— ์žˆ๋Š” ๋ฌธ์„œ๋“ค์ด ์„œ๋กœ ๋‹ค๋ฅธ ํ•„๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ด์•ผ.

์˜ˆ๋ฅผ ๋“ค์–ด๋ณผ๊ฒŒ:
// ์‚ฌ์šฉ์ž ๋ฌธ์„œ 1
{
  "_id": ObjectId("507f1f77bcf86cd799439011"),
  "name": "๊น€์ฒ ์ˆ˜",
  "email": "chulsoo@example.com",
  "age": 28
}

// ์‚ฌ์šฉ์ž ๋ฌธ์„œ 2 - ์ถ”๊ฐ€ ํ•„๋“œ๊ฐ€ ์žˆ์–ด๋„ OK!
{
  "_id": ObjectId("507f1f77bcf86cd799439012"),
  "name": "์ด์˜ํฌ",
  "email": "younghee@example.com",
  "age": 32,
  "address": {
    "city": "์„œ์šธ",
    "district": "๊ฐ•๋‚จ๊ตฌ"
  },
  "hobbies": ["๋…์„œ", "์—ฌํ–‰", "์š”๋ฆฌ"]
}
๋ณด๋‹ค์‹œํ”ผ ๋‘ ๋ฒˆ์งธ ๋ฌธ์„œ์—๋Š” address์™€ hobbies ํ•„๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜์–ด ์žˆ์ง€๋งŒ ์ „ํ˜€ ๋ฌธ์ œ์—†์–ด! ์ด๋Ÿฐ ์œ ์—ฐ์„ฑ ๋•๋ถ„์— ์• ์ž์ผ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ๋น ๋ฅด๊ฒŒ ํ”„๋กœํ† ํƒ€์ž…์„ ๋งŒ๋“ค๊ณ  ๋ฐ˜๋ณต ๊ฐœ์„ ํ•˜๊ธฐ์— ์ •๋ง ์ข‹์•„. ๐Ÿš€

2. ๊ฐ•๋ ฅํ•œ ์ฟผ๋ฆฌ ์–ธ์–ด

MongoDB๋Š” ํ’๋ถ€ํ•œ ์ฟผ๋ฆฌ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด. SQL๋งŒํผ์ด๋‚˜ ๋‹ค์–‘ํ•œ ์กฐ๊ฑด์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์–ด:
// ๋‚˜์ด๊ฐ€ 25์„ธ ์ด์ƒ์ด๊ณ  ์„œ์šธ์— ์‚ฌ๋Š” ์‚ฌ์šฉ์ž ์ฐพ๊ธฐ
db.users.find({
  age: { $gte: 25 },
  "address.city": "์„œ์šธ"
})

// ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ์„ ์‚ฌ์šฉํ•œ ๋ณต์žกํ•œ ๋ถ„์„
db.orders.aggregate([
  { $match: { status: "completed" } },
  { $group: { 
    _id: "$customerId", 
    totalAmount: { $sum: "$amount" } 
  }},
  { $sort: { totalAmount: -1 } },
  { $limit: 10 }
])
๐Ÿ’ก Pro Tip: MongoDB์˜ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ(Aggregation Pipeline)์€ ์ •๋ง ๊ฐ•๋ ฅํ•ด! ์—ฌ๋Ÿฌ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๊ณ  ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์–ด์„œ, ๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ ˆ๋ฒจ์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด.
3. ์ˆ˜ํ‰์  ํ™•์žฅ (Horizontal Scaling)

MongoDB๋Š” ์ƒค๋”ฉ(Sharding)์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ์„œ๋ฒ„์— ์ž๋™์œผ๋กœ ๋ถ„์‚ฐ์‹œ์ผœ. ๋ฐ์ดํ„ฐ๊ฐ€ ๋Š˜์–ด๋‚˜๋ฉด ์„œ๋ฒ„๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋˜๋‹ˆ๊นŒ ํ™•์žฅ์ด ์ •๋ง ์‰ฌ์›Œ! ๐Ÿ’ช

์ƒค๋”ฉ์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ์‚ดํŽด๋ณด๋ฉด:
MongoDB ์ƒค๋”ฉ ์•„ํ‚คํ…์ฒ˜ โ€ข Shard: ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” MongoDB ์ธ์Šคํ„ด์Šค
โ€ข Config Server: ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์™€ ํด๋Ÿฌ์Šคํ„ฐ ์„ค์ • ์ •๋ณด๋ฅผ ์ €์žฅ
โ€ข Mongos: ์ฟผ๋ฆฌ ๋ผ์šฐํ„ฐ ์—ญํ• , ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์„ ์ ์ ˆํ•œ ์ƒค๋“œ๋กœ ์ „๋‹ฌ
โ€ข Shard Key: ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ๋ถ„์‚ฐ์‹œํ‚ฌ์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๊ธฐ์ค€
4. ๋ณต์ œ์™€ ๊ณ ๊ฐ€์šฉ์„ฑ (Replication & High Availability)

MongoDB๋Š” ๋ ˆํ”Œ๋ฆฌ์นด ์…‹(Replica Set)์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ์„œ๋ฒ„์— ๋ณต์ œํ•ด. ์ฃผ ์„œ๋ฒ„(Primary)๊ฐ€ ๋‹ค์šด๋˜๋ฉด ์ž๋™์œผ๋กœ ๋ถ€ ์„œ๋ฒ„(Secondary) ์ค‘ ํ•˜๋‚˜๊ฐ€ ์ฃผ ์„œ๋ฒ„๋กœ ์Šน๊ฒฉ๋˜์–ด ์„œ๋น„์Šค ์ค‘๋‹จ ์—†์ด ์šด์˜ํ•  ์ˆ˜ ์žˆ์–ด! ๐Ÿ›ก๏ธ

๐Ÿ”ง MongoDB ์‹ค์ „ ํ™œ์šฉ ์‚ฌ๋ก€
์‹ค์ œ๋กœ MongoDB๋ฅผ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•˜๋Š”์ง€ ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ๋“ค์–ด๋ณผ๊ฒŒ:

์‚ฌ๋ก€ 1: ์ „์ž์ƒ๊ฑฐ๋ž˜ ์ƒํ’ˆ ์นดํƒˆ๋กœ๊ทธ

์ „์ž์ƒ๊ฑฐ๋ž˜ ์‚ฌ์ดํŠธ์—์„œ ์ƒํ’ˆ ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ด. ์ƒํ’ˆ๋งˆ๋‹ค ์†์„ฑ์ด ์ฒœ์ฐจ๋งŒ๋ณ„์ด์•ผ. ๋…ธํŠธ๋ถ์€ CPU, RAM, ์ €์žฅ์šฉ๋Ÿ‰ ๊ฐ™์€ ์ŠคํŽ™์ด ํ•„์š”ํ•˜์ง€๋งŒ, ์˜๋ฅ˜๋Š” ์‚ฌ์ด์ฆˆ, ์ƒ‰์ƒ, ์†Œ์žฌ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•˜์ง€. MongoDB์˜ ์œ ์—ฐํ•œ ์Šคํ‚ค๋งˆ๊ฐ€ ๋”ฑ์ด์•ผ!
// ๋…ธํŠธ๋ถ ์ƒํ’ˆ
{
  "productId": "LAPTOP001",
  "name": "๊ณ ์„ฑ๋Šฅ ๊ฒŒ์ด๋ฐ ๋…ธํŠธ๋ถ",
  "category": "์ „์ž์ œํ’ˆ",
  "price": 1500000,
  "specs": {
    "cpu": "Intel i7-12700H",
    "ram": "16GB DDR5",
    "storage": "512GB NVMe SSD",
    "gpu": "RTX 3060"
  },
  "reviews": [
    {
      "userId": "user123",
      "rating": 5,
      "comment": "์ •๋ง ๋น ๋ฅด๊ณ  ์ข‹์•„์š”!",
      "date": ISODate("2024-01-15")
    }
  ]
}

// ์˜๋ฅ˜ ์ƒํ’ˆ
{
  "productId": "SHIRT001",
  "name": "๋ฉด ๋ฐ˜ํŒ” ํ‹ฐ์…”์ธ ",
  "category": "์˜๋ฅ˜",
  "price": 29000,
  "sizes": ["S", "M", "L", "XL"],
  "colors": ["ํ™”์ดํŠธ", "๋ธ”๋ž™", "๋„ค์ด๋น„"],
  "material": "๋ฉด 100%",
  "reviews": []
}
์‚ฌ๋ก€ 2: ์‹ค์‹œ๊ฐ„ ๋กœ๊ทธ ์ˆ˜์ง‘ ๋ฐ ๋ถ„์„

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊ทธ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ˆ˜์ง‘ํ•˜๊ณ  ๋ถ„์„ํ•˜๋Š” ์‹œ์Šคํ…œ์—๋„ MongoDB๊ฐ€ ์ž์ฃผ ์‚ฌ์šฉ๋ผ. ๋กœ๊ทธ ๋ฐ์ดํ„ฐ๋Š” ๊ตฌ์กฐ๊ฐ€ ๋‹ค์–‘ํ•˜๊ณ  ์–‘์ด ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ์œ ์—ฐ์„ฑ๊ณผ ํ™•์žฅ์„ฑ์ด ์ค‘์š”ํ•˜๊ฑฐ๋“ .
// ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊ทธ ๋ฌธ์„œ
{
  "timestamp": ISODate("2024-01-20T10:30:45Z"),
  "level": "ERROR",
  "service": "payment-service",
  "message": "๊ฒฐ์ œ ์ฒ˜๋ฆฌ ์‹คํŒจ",
  "errorCode": "PAYMENT_GATEWAY_TIMEOUT",
  "userId": "user456",
  "metadata": {
    "orderId": "ORD123456",
    "amount": 50000,
    "gateway": "PG์‚ฌA"
  },
  "stackTrace": "..."
}
โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ: MongoDB๋Š” ๊ฐ•๋ ฅํ•˜์ง€๋งŒ ๋งŒ๋Šฅ์€ ์•„๋‹ˆ์•ผ! ๋ณต์žกํ•œ ํŠธ๋žœ์žญ์…˜์ด ๋งŽ์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜, ๋ฐ์ดํ„ฐ ๊ฐ„์˜ ๊ด€๊ณ„๊ฐ€ ๋งค์šฐ ๋ณต์žกํ•œ ๊ฒฝ์šฐ์—๋Š” ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๋” ์ ํ•ฉํ•  ์ˆ˜ ์žˆ์–ด. ํ•ญ์ƒ ํ”„๋กœ์ ํŠธ์˜ ์š”๊ตฌ์‚ฌํ•ญ์„ ๋จผ์ € ๋ถ„์„ํ•˜๊ณ  ์„ ํƒํ•ด์•ผ ํ•ด!
โšก MongoDB ์„ฑ๋Šฅ ์ตœ์ ํ™” ํŒ
MongoDB๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์„ฑ๋Šฅ์„ ๊ทน๋Œ€ํ™”ํ•˜๋ ค๋ฉด ๋ช‡ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ํฌ์ธํŠธ๊ฐ€ ์žˆ์–ด:

1. ์ธ๋ฑ์Šค ์ „๋žต

์ ์ ˆํ•œ ์ธ๋ฑ์Šค๋Š” ์ฟผ๋ฆฌ ์„ฑ๋Šฅ์„ ์ˆ˜์‹ญ ๋ฐฐ์—์„œ ์ˆ˜๋ฐฑ ๋ฐฐ๊นŒ์ง€ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด!
// ๋‹จ์ผ ํ•„๋“œ ์ธ๋ฑ์Šค
db.users.createIndex({ email: 1 })

// ๋ณตํ•ฉ ์ธ๋ฑ์Šค (์ž์ฃผ ํ•จ๊ป˜ ์กฐํšŒ๋˜๋Š” ํ•„๋“œ๋“ค)
db.orders.createIndex({ customerId: 1, orderDate: -1 })

// ํ…์ŠคํŠธ ์ธ๋ฑ์Šค (์ „๋ฌธ ๊ฒ€์ƒ‰์šฉ)
db.articles.createIndex({ title: "text", content: "text" })

// ์ง€๋ฆฌ๊ณต๊ฐ„ ์ธ๋ฑ์Šค (์œ„์น˜ ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰)
db.places.createIndex({ location: "2dsphere" })
2. ์ฟผ๋ฆฌ ์ตœ์ ํ™”

โ€ข explain() ๋ฉ”์„œ๋“œ๋กœ ์ฟผ๋ฆฌ ์‹คํ–‰ ๊ณ„ํš์„ ๋ถ„์„ํ•ด
โ€ข ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ์„ ํƒํ•ด์„œ ๊ฐ€์ ธ์™€ (Projection ์‚ฌ์šฉ)
โ€ข ํŽ˜์ด์ง€๋„ค์ด์…˜ ๊ตฌํ˜„ ์‹œ skip()๋ณด๋‹ค๋Š” ๋ฒ”์œ„ ์ฟผ๋ฆฌ ์‚ฌ์šฉ
โ€ข ๋Œ€๋Ÿ‰ ์—…๋ฐ์ดํŠธ๋Š” bulkWrite() ํ™œ์šฉ

3. ๋ฌธ์„œ ์„ค๊ณ„ ์›์น™

โ€ข ์ž์ฃผ ํ•จ๊ป˜ ์กฐํšŒ๋˜๋Š” ๋ฐ์ดํ„ฐ๋Š” ์ž„๋ฒ ๋”ฉ(Embedding)์œผ๋กœ ํ•œ ๋ฌธ์„œ์— ํฌํ•จ
โ€ข ๋…๋ฆฝ์ ์œผ๋กœ ๊ด€๋ฆฌ๋˜์–ด์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋Š” ์ฐธ์กฐ(Reference) ๋ฐฉ์‹ ์‚ฌ์šฉ
โ€ข ๋ฌธ์„œ ํฌ๊ธฐ๋Š” 16MB ์ œํ•œ์„ ๊ณ ๋ ค (์ผ๋ฐ˜์ ์œผ๋กœ ์ˆ˜ KB ์ด๋‚ด ๊ถŒ์žฅ)
โ€ข ๋ฐฐ์—ด ํ•„๋“œ์˜ ํฌ๊ธฐ๊ฐ€ ๋ฌดํ•œ์ • ์ปค์ง€์ง€ ์•Š๋„๋ก ์ฃผ์˜

## ๐ŸŒŸ Apache Cassandra: ๋ถ„์‚ฐ ํ™˜๊ฒฝ์˜ ์ตœ๊ฐ•์ž ์ด์ œ Cassandra์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ์ฐจ๋ก€์•ผ! Cassandra๋Š” Facebook์—์„œ ๊ฐœ๋ฐœํ–ˆ๋‹ค๊ฐ€ Apache ์žฌ๋‹จ์— ๊ธฐ์ฆ๋œ ์˜คํ”ˆ์†Œ์Šค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์•ผ. Netflix, Apple, Instagram ๊ฐ™์€ ๊ธ€๋กœ๋ฒŒ ๊ธฐ์—…๋“ค์ด ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์–ด. ์™œ ์ด๋ ‡๊ฒŒ ์ธ๊ธฐ๊ฐ€ ๋งŽ์„๊นŒ? ๐ŸŒ

๐Ÿ’Ž Cassandra์˜ ํ•ต์‹ฌ ํŠน์ง•
1. ๋งˆ์Šคํ„ฐ๋ฆฌ์Šค ์•„ํ‚คํ…์ฒ˜ (Masterless Architecture)

Cassandra์˜ ๊ฐ€์žฅ ํฐ ํŠน์ง•์€ ๋ชจ๋“  ๋…ธ๋“œ๊ฐ€ ๋™๋“ฑํ•˜๋‹ค๋Š” ๊ฑฐ์•ผ! MongoDB์˜ ๋ ˆํ”Œ๋ฆฌ์นด ์…‹์ฒ˜๋Ÿผ Primary-Secondary ๊ตฌ์กฐ๊ฐ€ ์•„๋‹ˆ๋ผ, ๋ชจ๋“  ๋…ธ๋“œ๊ฐ€ ์ฝ๊ธฐ์™€ ์“ฐ๊ธฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด. ์ด๋ฅผ ํ”ผ์–ด-ํˆฌ-ํ”ผ์–ด(Peer-to-Peer) ์•„ํ‚คํ…์ฒ˜๋ผ๊ณ  ํ•ด. ๐Ÿ”„

์ด๊ฒŒ ์™œ ์ค‘์š”ํ•˜๋ƒ๊ณ ? ๋‹จ์ผ ์žฅ์• ์ (Single Point of Failure)์ด ์—†๋‹ค๋Š” ๋œป์ด์•ผ! ์–ด๋–ค ๋…ธ๋“œ๊ฐ€ ๋‹ค์šด๋˜์–ด๋„ ๋‹ค๋ฅธ ๋…ธ๋“œ๋“ค์ด ๊ณ„์† ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์–ด. ์ง„์ •ํ•œ ์˜๋ฏธ์˜ ๊ณ ๊ฐ€์šฉ์„ฑ์ด์ง€!

2. ์„ ํ˜•์  ํ™•์žฅ์„ฑ (Linear Scalability)

Cassandra๋Š” ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์„ฑ๋Šฅ์ด ๊ฑฐ์˜ ์„ ํ˜•์ ์œผ๋กœ ์ฆ๊ฐ€ํ•ด. ๋…ธ๋“œ๊ฐ€ 2๋ฐฐ๊ฐ€ ๋˜๋ฉด ์ฒ˜๋ฆฌ๋Ÿ‰๋„ ๊ฑฐ์˜ 2๋ฐฐ๊ฐ€ ๋˜๋Š” ๊ฑฐ์ง€. ์ด๊ฑด ์ •๋ง ๋†€๋ผ์šด ํŠน์„ฑ์ด์•ผ! ๐Ÿ“ˆ

ํ™•์žฅ์„ฑ ๋น„๊ต โ€ข 1๊ฐœ ๋…ธ๋“œ: 10,000 writes/sec
โ€ข 2๊ฐœ ๋…ธ๋“œ: ~20,000 writes/sec
โ€ข 4๊ฐœ ๋…ธ๋“œ: ~40,000 writes/sec
โ€ข 8๊ฐœ ๋…ธ๋“œ: ~80,000 writes/sec

์‹ค์ œ๋กœ๋Š” ๋„คํŠธ์›Œํฌ ์˜ค๋ฒ„ํ—ค๋“œ ๋“ฑ์œผ๋กœ ์™„๋ฒฝํ•œ ์„ ํ˜•์€ ์•„๋‹ˆ์ง€๋งŒ, ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋น„ํ•ด ์›”๋“ฑํžˆ ๋›ฐ์–ด๋‚œ ํ™•์žฅ์„ฑ์„ ๋ณด์—ฌ์ค˜!
3. ์ดˆ๊ณ ์† ์“ฐ๊ธฐ ์„ฑ๋Šฅ

Cassandra๋Š” ์“ฐ๊ธฐ ์ตœ์ ํ™” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์•ผ. LSM Tree(Log-Structured Merge Tree) ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์“ฐ๊ธฐ ์ž‘์—…์ด ์—„์ฒญ๋‚˜๊ฒŒ ๋นจ๋ผ. ๋ฐ์ดํ„ฐ๋ฅผ ๋จผ์ € ๋ฉ”๋ชจ๋ฆฌ์˜ Memtable์— ์“ฐ๊ณ , ๋‚˜์ค‘์— ๋””์Šคํฌ์˜ SSTable๋กœ ํ”Œ๋Ÿฌ์‹œํ•˜๋Š” ๋ฐฉ์‹์ด์•ผ. โšก

์“ฐ๊ธฐ ํ”„๋กœ์„ธ์Šค:
1. CommitLog์— ๋จผ์ € ๊ธฐ๋ก (๋‚ด๊ตฌ์„ฑ ๋ณด์žฅ)
2. Memtable(๋ฉ”๋ชจ๋ฆฌ)์— ๋ฐ์ดํ„ฐ ์ €์žฅ
3. Memtable์ด ๊ฐ€๋“ ์ฐจ๋ฉด SSTable(๋””์Šคํฌ)๋กœ ํ”Œ๋Ÿฌ์‹œ
4. ์ฃผ๊ธฐ์ ์œผ๋กœ SSTable๋“ค์„ Compaction (๋ณ‘ํ•ฉ ๋ฐ ์ตœ์ ํ™”)
4. ํŠœ๋‹ ๊ฐ€๋Šฅํ•œ ์ผ๊ด€์„ฑ (Tunable Consistency)

Cassandra๋Š” CAP ์ •๋ฆฌ์—์„œ AP(Availability + Partition Tolerance)๋ฅผ ์„ ํƒํ•œ ์‹œ์Šคํ…œ์ด์•ผ. ํ•˜์ง€๋งŒ ์ผ๊ด€์„ฑ ๋ ˆ๋ฒจ์„ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์–ด์„œ ์ƒํ™ฉ์— ๋งž๊ฒŒ ์„ ํƒํ•  ์ˆ˜ ์žˆ์–ด! ๐ŸŽš๏ธ

์ผ๊ด€์„ฑ ๋ ˆ๋ฒจ ์„ค๋ช… ์‚ฌ์šฉ ์‚ฌ๋ก€
ONE 1๊ฐœ ๋…ธ๋“œ๋งŒ ์‘๋‹ตํ•˜๋ฉด OK ์ตœ๊ณ  ์„ฑ๋Šฅ, ๋‚ฎ์€ ์ผ๊ด€์„ฑ ์š”๊ตฌ
QUORUM ๊ณผ๋ฐ˜์ˆ˜ ๋…ธ๋“œ๊ฐ€ ์‘๋‹ต ๊ท ํ˜•์žกํžŒ ์„ ํƒ (๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ)
ALL ๋ชจ๋“  ๋ณต์ œ๋ณธ์ด ์‘๋‹ต ์ตœ๊ณ  ์ผ๊ด€์„ฑ, ๋‚ฎ์€ ๊ฐ€์šฉ์„ฑ
LOCAL_QUORUM ๊ฐ™์€ ๋ฐ์ดํ„ฐ์„ผํ„ฐ ๋‚ด ๊ณผ๋ฐ˜์ˆ˜ ๋‹ค์ค‘ ๋ฐ์ดํ„ฐ์„ผํ„ฐ ํ™˜๊ฒฝ
๐Ÿ’ก ์ผ๊ด€์„ฑ ๋ ˆ๋ฒจ ์„ ํƒ ํŒ: ์ฝ๊ธฐ์™€ ์“ฐ๊ธฐ์˜ ์ผ๊ด€์„ฑ ๋ ˆ๋ฒจ์„ ์กฐํ•ฉํ•ด์„œ ๊ฐ•ํ•œ ์ผ๊ด€์„ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์–ด. ์˜ˆ๋ฅผ ๋“ค์–ด Write: QUORUM + Read: QUORUM์ด๋ฉด ํ•ญ์ƒ ์ตœ์‹  ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ์–ด!
๐Ÿ—๏ธ Cassandra ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง
Cassandra์˜ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง์€ ๊ด€๊ณ„ํ˜• DB๋‚˜ MongoDB์™€๋Š” ์™„์ „ํžˆ ๋‹ค๋ฅธ ์ ‘๊ทผ์ด ํ•„์š”ํ•ด. ์ฟผ๋ฆฌ ์ค‘์‹ฌ ์„ค๊ณ„๊ฐ€ ํ•ต์‹ฌ์ด์•ผ!

๊ธฐ๋ณธ ๊ฐœ๋…:

โ€ข Keyspace: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์œ ์‚ฌํ•œ ์ตœ์ƒ์œ„ ์ปจํ…Œ์ด๋„ˆ
โ€ข Table: ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ตฌ์กฐ
โ€ข Partition Key: ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋А ๋…ธ๋“œ์— ์ €์žฅํ• ์ง€ ๊ฒฐ์ •
โ€ข Clustering Key: ํŒŒํ‹ฐ์…˜ ๋‚ด์—์„œ ๋ฐ์ดํ„ฐ ์ •๋ ฌ ๊ธฐ์ค€
โ€ข Primary Key: Partition Key + Clustering Key

์˜ˆ์ œ: ์‹œ๊ณ„์—ด ์„ผ์„œ ๋ฐ์ดํ„ฐ
CREATE KEYSPACE sensor_data WITH replication = {
  'class': 'NetworkTopologyStrategy',
  'datacenter1': 3
};

CREATE TABLE sensor_readings (
  sensor_id text,
  reading_date date,
  reading_time timestamp,
  temperature decimal,
  humidity decimal,
  pressure decimal,
  PRIMARY KEY ((sensor_id, reading_date), reading_time)
) WITH CLUSTERING ORDER BY (reading_time DESC);
์ด ์„ค๊ณ„์—์„œ:
โ€ข sensor_id์™€ reading_date๊ฐ€ Partition Key (ํ•จ๊ป˜ ํ•ด์‹œ๋˜์–ด ๋…ธ๋“œ ๊ฒฐ์ •)
โ€ข reading_time์ด Clustering Key (์‹œ๊ฐ„ ์—ญ์ˆœ์œผ๋กœ ์ •๋ ฌ)
โ€ข ํŠน์ • ์„ผ์„œ์˜ ํŠน์ • ๋‚ ์งœ ๋ฐ์ดํ„ฐ๋ฅผ ๋น ๋ฅด๊ฒŒ ์กฐํšŒ ๊ฐ€๋Šฅ

๋ฐ์ดํ„ฐ ์‚ฝ์ž…:
INSERT INTO sensor_readings (
  sensor_id, reading_date, reading_time, 
  temperature, humidity, pressure
) VALUES (
  'SENSOR_001', '2024-01-20', '2024-01-20 14:30:00',
  23.5, 65.2, 1013.25
);
๋ฐ์ดํ„ฐ ์กฐํšŒ:
// ํŠน์ • ์„ผ์„œ์˜ ์˜ค๋Š˜ ๋ฐ์ดํ„ฐ ์กฐํšŒ
SELECT * FROM sensor_readings 
WHERE sensor_id = 'SENSOR_001' 
  AND reading_date = '2024-01-20'
ORDER BY reading_time DESC
LIMIT 100;

// ์‹œ๊ฐ„ ๋ฒ”์œ„ ์กฐํšŒ
SELECT * FROM sensor_readings 
WHERE sensor_id = 'SENSOR_001' 
  AND reading_date = '2024-01-20'
  AND reading_time >= '2024-01-20 10:00:00'
  AND reading_time < '2024-01-20 15:00:00';
โš ๏ธ Cassandra ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง ์ฃผ์˜์‚ฌํ•ญ: โ€ข ์กฐ์ธ(JOIN)์ด ์—†์–ด! ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋Š” ๋ฏธ๋ฆฌ ๋น„์ •๊ทœํ™”ํ•ด์„œ ์ €์žฅ
โ€ข Partition Key ์—†์ด๋Š” ์กฐํšŒ ๋ถˆ๊ฐ€ (Full table scan ์ง€์–‘)
โ€ข ํŒŒํ‹ฐ์…˜์ด ๋„ˆ๋ฌด ์ปค์ง€์ง€ ์•Š๋„๋ก ์ฃผ์˜ (๊ถŒ์žฅ: 100MB ์ดํ•˜)
โ€ข ์ฟผ๋ฆฌ ํŒจํ„ด์„ ๋จผ์ € ์ •์˜ํ•˜๊ณ  ํ…Œ์ด๋ธ” ์„ค๊ณ„
๐ŸŽฏ Cassandra ์‹ค์ „ ํ™œ์šฉ ์‚ฌ๋ก€
์‚ฌ๋ก€ 1: Netflix์˜ ์‹œ์ฒญ ๊ธฐ๋ก ๊ด€๋ฆฌ

Netflix๋Š” ์ˆ˜์–ต ๋ช…์˜ ์‚ฌ์šฉ์ž ์‹œ์ฒญ ๊ธฐ๋ก์„ Cassandra๋กœ ๊ด€๋ฆฌํ•ด. ์ดˆ๋‹น ์ˆ˜๋ฐฑ๋งŒ ๊ฑด์˜ ์“ฐ๊ธฐ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๋ฐ, Cassandra์˜ ๋›ฐ์–ด๋‚œ ์“ฐ๊ธฐ ์„ฑ๋Šฅ๊ณผ ํ™•์žฅ์„ฑ์ด ์™„๋ฒฝํ•˜๊ฒŒ ๋“ค์–ด๋งž๋Š” ๊ฑฐ์ง€!

์‚ฌ๋ก€ 2: IoT ์„ผ์„œ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘

์ˆ˜์ฒœ, ์ˆ˜๋งŒ ๊ฐœ์˜ IoT ์„ผ์„œ์—์„œ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ์Ÿ์•„์ ธ ๋“ค์–ด์™€. ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ €์žฅํ•˜๊ณ  ์กฐํšŒํ•˜๋Š” ๋ฐ Cassandra๊ฐ€ ์ตœ์ ์ด์•ผ. ์‹œ๊ฐ„ ๊ธฐ๋ฐ˜ ํŒŒํ‹ฐ์…”๋‹์œผ๋กœ ์˜ค๋ž˜๋œ ๋ฐ์ดํ„ฐ๋Š” ์ž๋™์œผ๋กœ ์‚ญ์ œ(TTL)ํ•  ์ˆ˜๋„ ์žˆ์–ด!

์‚ฌ๋ก€ 3: ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ

๋Œ€๊ทœ๋ชจ ์ฑ„ํŒ… ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋‚˜ ๋ฉ”์‹œ์ง• ์‹œ์Šคํ…œ์—์„œ๋„ Cassandra๊ฐ€ ์ž์ฃผ ์‚ฌ์šฉ๋ผ. ์‚ฌ์šฉ์ž๋ณ„๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ๋น ๋ฅด๊ฒŒ ์ €์žฅํ•˜๊ณ  ์กฐํšŒํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ .
CREATE TABLE messages (
  user_id uuid,
  conversation_id uuid,
  message_time timestamp,
  message_id uuid,
  sender_id uuid,
  content text,
  PRIMARY KEY ((user_id, conversation_id), message_time, message_id)
) WITH CLUSTERING ORDER BY (message_time DESC, message_id DESC);
โš™๏ธ Cassandra ์šด์˜ ๋ฐ ์ตœ์ ํ™”
1. ๋ณต์ œ ์ „๋žต (Replication Strategy)

โ€ข SimpleStrategy: ๋‹จ์ผ ๋ฐ์ดํ„ฐ์„ผํ„ฐ ํ™˜๊ฒฝ (๊ฐœ๋ฐœ/ํ…Œ์ŠคํŠธ์šฉ)
โ€ข NetworkTopologyStrategy: ๋‹ค์ค‘ ๋ฐ์ดํ„ฐ์„ผํ„ฐ ํ™˜๊ฒฝ (ํ”„๋กœ๋•์…˜ ๊ถŒ์žฅ)

// ๋‹ค์ค‘ ๋ฐ์ดํ„ฐ์„ผํ„ฐ ๋ณต์ œ ์„ค์ •
CREATE KEYSPACE my_app WITH replication = {
  'class': 'NetworkTopologyStrategy',
  'dc1': 3,  // ๋ฐ์ดํ„ฐ์„ผํ„ฐ1์— 3๊ฐœ ๋ณต์ œ๋ณธ
  'dc2': 2   // ๋ฐ์ดํ„ฐ์„ผํ„ฐ2์— 2๊ฐœ ๋ณต์ œ๋ณธ
};
2. Compaction ์ „๋žต

Cassandra๋Š” ์ฃผ๊ธฐ์ ์œผ๋กœ SSTable์„ ๋ณ‘ํ•ฉํ•˜๋Š” Compaction ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด. ์ „๋žต์— ๋”ฐ๋ผ ์„ฑ๋Šฅ์ด ํฌ๊ฒŒ ๋‹ฌ๋ผ์ ธ!

โ€ข SizeTieredCompactionStrategy (STCS): ๊ธฐ๋ณธ ์ „๋žต, ์“ฐ๊ธฐ ์œ„์ฃผ ์›Œํฌ๋กœ๋“œ
โ€ข LeveledCompactionStrategy (LCS): ์ฝ๊ธฐ ์œ„์ฃผ ์›Œํฌ๋กœ๋“œ, ๊ณต๊ฐ„ ํšจ์œจ์ 
โ€ข TimeWindowCompactionStrategy (TWCS): ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ, TTL ์‚ฌ์šฉ ์‹œ ์ตœ์ 

3. ๋ชจ๋‹ˆํ„ฐ๋ง ํฌ์ธํŠธ

โ€ข Read/Write Latency: ์‘๋‹ต ์‹œ๊ฐ„ ์ถ”์ 
โ€ข Pending Tasks: ๋Œ€๊ธฐ ์ค‘์ธ ์ž‘์—… ์ˆ˜
โ€ข Compaction ์ƒํƒœ: ๋””์Šคํฌ I/O ์˜ํ–ฅ
โ€ข Heap Memory ์‚ฌ์šฉ๋ฅ : GC ์„ฑ๋Šฅ ์˜ํ–ฅ
โ€ข Disk Space: SSTable ํฌ๊ธฐ ๋ชจ๋‹ˆํ„ฐ๋ง

Cassandra ๋ถ„์‚ฐ ์•„ํ‚คํ…์ฒ˜ Cassandra Ring Node 1 Token: 0 Node 2 Token: 42 Node 3 Token: 85 Node 4 Token: 127 Node 5 Token: 170 Node 6 Token: 212 ์ฃผ์š” ํŠน์ง• โœ“ ๋งˆ์Šคํ„ฐ๋ฆฌ์Šค ๋ชจ๋“  ๋…ธ๋“œ๊ฐ€ ๋™๋“ฑ โœ“ ์ž๋™ ์ƒค๋”ฉ ํ† ํฐ ๊ธฐ๋ฐ˜ ๋ถ„์‚ฐ โœ“ ๊ณ ๊ฐ€์šฉ์„ฑ ๋ณต์ œ๋ณธ ์ž๋™ ๊ด€๋ฆฌ โœ“ ์„ ํ˜• ํ™•์žฅ ๋…ธ๋“œ ์ถ”๊ฐ€๋กœ ์„ฑ๋Šฅโ†‘ โœ“ ์ดˆ๊ณ ์† ์“ฐ๊ธฐ LSM Tree ๊ตฌ์กฐ โœ“ ํŠœ๋‹ ๊ฐ€๋Šฅ ์ผ๊ด€์„ฑ ๋ ˆ๋ฒจ ์กฐ์ • Client Request ์–ด๋А ๋…ธ๋“œ๋“  ์ ‘๊ทผ ๊ฐ€๋Šฅ
## ๐Ÿ”„ MongoDB vs Cassandra: ์–ด๋–ค ๊ฑธ ์„ ํƒํ•ด์•ผ ํ• ๊นŒ? ์ž, ์ด์ œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์งˆ๋ฌธ์ด์•ผ. MongoDB์™€ Cassandra ์ค‘์—์„œ ์–ด๋–ค ๊ฑธ ์„ ํƒํ•ด์•ผ ํ• ๊นŒ? ์ •๋‹ต์€... "์ƒํ™ฉ์— ๋”ฐ๋ผ ๋‹ค๋ฅด๋‹ค"์•ผ! ๐Ÿ˜… ๊ฐ๊ฐ์˜ ๊ฐ•์ ์ด ๋‹ค๋ฅด๋‹ˆ๊นŒ ํ”„๋กœ์ ํŠธ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ž˜ ๋ถ„์„ํ•ด์•ผ ํ•ด.

๐Ÿƒ MongoDB๋ฅผ ์„ ํƒํ•ด์•ผ ํ•  ๋•Œ

โœ… ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๋•Œ
โœ… ์Šคํ‚ค๋งˆ๊ฐ€ ์ž์ฃผ ๋ณ€๊ฒฝ๋  ๋•Œ
โœ… ๋ฌธ์„œ ๋‹จ์œ„ ํŠธ๋žœ์žญ์…˜์ด ํ•„์š”ํ•  ๋•Œ
โœ… ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ๋ฐ์ดํ„ฐ ๋ถ„์„
โœ… ๊ฐœ๋ฐœ ์†๋„๊ฐ€ ์ค‘์š”ํ•  ๋•Œ
โœ… ์ค‘์†Œ๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ
๐ŸŒŸ Cassandra๋ฅผ ์„ ํƒํ•ด์•ผ ํ•  ๋•Œ

โœ… ์ดˆ๋Œ€๊ทœ๋ชจ ์“ฐ๊ธฐ ์ž‘์—…์ด ๋งŽ์„ ๋•Œ
โœ… ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ
โœ… ๋‹ค์šดํƒ€์ž„์ด ์ ˆ๋Œ€ ์•ˆ ๋  ๋•Œ
โœ… ์ง€๋ฆฌ์ ์œผ๋กœ ๋ถ„์‚ฐ๋œ ํ™˜๊ฒฝ
โœ… ์„ ํ˜•์  ํ™•์žฅ์ด ํ•„์š”ํ•  ๋•Œ
โœ… ๋‹จ์ˆœํ•˜์ง€๋งŒ ๋น ๋ฅธ ์กฐํšŒ
๐Ÿ“Š ์ƒ์„ธ ๋น„๊ตํ‘œ
๋น„๊ต ํ•ญ๋ชฉ MongoDB Cassandra
๋ฐ์ดํ„ฐ ๋ชจ๋ธ ๋ฌธ์„œ ์ง€ํ–ฅ (JSON/BSON) ์ปฌ๋Ÿผ ํŒจ๋ฐ€๋ฆฌ (Wide Column)
์ฟผ๋ฆฌ ์–ธ์–ด MongoDB Query Language (ํ’๋ถ€) CQL (SQL-like, ์ œํ•œ์ )
์Šคํ‚ค๋งˆ ์œ ์—ฐํ•œ ๋™์  ์Šคํ‚ค๋งˆ ์ •์˜๋œ ์Šคํ‚ค๋งˆ (๋ณ€๊ฒฝ ๊ฐ€๋Šฅ)
์“ฐ๊ธฐ ์„ฑ๋Šฅ ๋น ๋ฆ„ ๋งค์šฐ ๋น ๋ฆ„ (์ตœ์ ํ™”)
์ฝ๊ธฐ ์„ฑ๋Šฅ ๋น ๋ฆ„ (์ธ๋ฑ์Šค ํ™œ์šฉ) ๋น ๋ฆ„ (ํŒŒํ‹ฐ์…˜ ํ‚ค ์กฐํšŒ)
ํ™•์žฅ์„ฑ ์ƒค๋”ฉ (์ˆ˜ํ‰ ํ™•์žฅ ๊ฐ€๋Šฅ) ์„ ํ˜•์  ํ™•์žฅ (๋งค์šฐ ์šฐ์ˆ˜)
์ผ๊ด€์„ฑ ๊ฐ•ํ•œ ์ผ๊ด€์„ฑ (๊ธฐ๋ณธ) ์ตœ์ข… ์ผ๊ด€์„ฑ (ํŠœ๋‹ ๊ฐ€๋Šฅ)
ํŠธ๋žœ์žญ์…˜ ACID ํŠธ๋žœ์žญ์…˜ ์ง€์› ๊ฒฝ๋Ÿ‰ ํŠธ๋žœ์žญ์…˜ (์ œํ•œ์ )
๋ณต์ œ ๋ ˆํ”Œ๋ฆฌ์นด ์…‹ (Primary-Secondary) ํ”ผ์–ด-ํˆฌ-ํ”ผ์–ด (๋งˆ์Šคํ„ฐ๋ฆฌ์Šค)
์กฐ์ธ $lookup์œผ๋กœ ๊ฐ€๋Šฅ (์ œํ•œ์ ) ๋ถˆ๊ฐ€๋Šฅ (๋น„์ •๊ทœํ™” ํ•„์š”)
์ง‘๊ณ„ ๊ฐ•๋ ฅํ•œ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ ์ œํ•œ์  (์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ ˆ๋ฒจ)
ํ•™์Šต ๊ณก์„  ๋น„๊ต์  ์‰ฌ์›€ ๊ฐ€ํŒŒ๋ฆ„ (๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง ๋ณต์žก)
์šด์˜ ๋ณต์žก๋„ ์ค‘๊ฐ„ ๋†’์Œ
์ปค๋ฎค๋‹ˆํ‹ฐ ๋งค์šฐ ํ™œ๋ฐœ ํ™œ๋ฐœ
์‚ฌ์šฉ ๊ธฐ์—… Uber, eBay, Adobe Netflix, Apple, Instagram
๐ŸŽฏ ์‹ค์ „ ์„ ํƒ ๊ฐ€์ด๋“œ
์‹œ๋‚˜๋ฆฌ์˜ค 1: ์ „์ž์ƒ๊ฑฐ๋ž˜ ํ”Œ๋žซํผ ์š”๊ตฌ์‚ฌํ•ญ: ์ƒํ’ˆ ์นดํƒˆ๋กœ๊ทธ, ์ฃผ๋ฌธ ๊ด€๋ฆฌ, ์‚ฌ์šฉ์ž ๋ฆฌ๋ทฐ, ์žฌ๊ณ  ๊ด€๋ฆฌ
์ถ”์ฒœ: MongoDB
์ด์œ : ์ƒํ’ˆ๋งˆ๋‹ค ๋‹ค๋ฅธ ์†์„ฑ, ๋ณต์žกํ•œ ์ฟผ๋ฆฌ ํ•„์š”, ํŠธ๋žœ์žญ์…˜ ์ค‘์š”, ์ง‘๊ณ„ ๋ถ„์„ ํ•„์š”
์‹œ๋‚˜๋ฆฌ์˜ค 2: IoT ์„ผ์„œ ๋ฐ์ดํ„ฐ ํ”Œ๋žซํผ ์š”๊ตฌ์‚ฌํ•ญ: ์ˆ˜์ฒœ ๊ฐœ ์„ผ์„œ์—์„œ ์ดˆ๋‹น ์ˆ˜๋งŒ ๊ฑด ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘, ์‹œ๊ณ„์—ด ๋ถ„์„
์ถ”์ฒœ: Cassandra
์ด์œ : ๋Œ€๋Ÿ‰ ์“ฐ๊ธฐ ์ตœ์ ํ™”, ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ, TTL ์ž๋™ ์‚ญ์ œ, ์„ ํ˜• ํ™•์žฅ
์‹œ๋‚˜๋ฆฌ์˜ค 3: ์†Œ์…œ ๋ฏธ๋””์–ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์š”๊ตฌ์‚ฌํ•ญ: ์‚ฌ์šฉ์ž ํ”„๋กœํ•„, ๊ฒŒ์‹œ๋ฌผ, ๋Œ“๊ธ€, ์ข‹์•„์š”, ํŒ”๋กœ์šฐ ๊ด€๊ณ„
์ถ”์ฒœ: MongoDB (๋˜๋Š” ํ•˜์ด๋ธŒ๋ฆฌ๋“œ)
์ด์œ : ์œ ์—ฐํ•œ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ, ๋ณต์žกํ•œ ์ฟผ๋ฆฌ, ์‹ค์‹œ๊ฐ„ ํ”ผ๋“œ ์ƒ์„ฑ. ๋‹จ, ํƒ€์ž„๋ผ์ธ์€ Cassandra ํ™œ์šฉ ๊ฐ€๋Šฅ
์‹œ๋‚˜๋ฆฌ์˜ค 4: ์‹ค์‹œ๊ฐ„ ๋กœ๊ทธ ๋ถ„์„ ์‹œ์Šคํ…œ ์š”๊ตฌ์‚ฌํ•ญ: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊ทธ ์ˆ˜์ง‘, ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง, ์žฅ๊ธฐ ๋ณด๊ด€
์ถ”์ฒœ: Cassandra
์ด์œ : ์ดˆ๊ณ ์† ์“ฐ๊ธฐ, ์‹œ๊ฐ„ ๊ธฐ๋ฐ˜ ํŒŒํ‹ฐ์…”๋‹, ์••์ถ• ํšจ์œจ, ๋‹ค์šดํƒ€์ž„ ์—†๋Š” ์šด์˜
๐Ÿ’ก ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ ‘๊ทผ๋ฒ•: ๋งŽ์€ ๋Œ€๊ทœ๋ชจ ์‹œ์Šคํ…œ์—์„œ๋Š” MongoDB์™€ Cassandra๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด! ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž ํ”„๋กœํ•„๊ณผ ์ƒํ’ˆ ์ •๋ณด๋Š” MongoDB์—, ํ™œ๋™ ๋กœ๊ทธ์™€ ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ๋Š” Cassandra์— ์ €์žฅํ•˜๋Š” ์‹์ด์•ผ. ๊ฐ ๋„๊ตฌ์˜ ๊ฐ•์ ์„ ์‚ด๋ฆฌ๋Š” ๊ฑฐ์ง€! ๐ŸŽจ
## ๐Ÿ› ๏ธ ์‹ค์ „ ๊ตฌ์ถ• ๊ฐ€์ด๋“œ: ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ์ด๋ก ๋งŒ ์•Œ์•„์„œ๋Š” ๋ถ€์กฑํ•˜์ง€! ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ๊ตฌ์ถ•ํ•˜๊ณ  ์šด์˜ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด์ž. ๐Ÿ˜Š

๐Ÿš€ MongoDB ํด๋Ÿฌ์Šคํ„ฐ ๊ตฌ์ถ•ํ•˜๊ธฐ
1๋‹จ๊ณ„: ๋ ˆํ”Œ๋ฆฌ์นด ์…‹ ๊ตฌ์„ฑ

ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ์ตœ์†Œ 3๊ฐœ ๋…ธ๋“œ๋กœ ๋ ˆํ”Œ๋ฆฌ์นด ์…‹์„ ๊ตฌ์„ฑํ•ด์•ผ ํ•ด. ํ™€์ˆ˜ ๊ฐœ์˜ ๋…ธ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์„ ๊ฑฐ(Election) ๊ณผ์ •์—์„œ ์œ ๋ฆฌํ•ด!
// mongod.conf ์„ค์ • (๊ฐ ๋…ธ๋“œ)
replication:
  replSetName: "myReplicaSet"

net:
  bindIp: 0.0.0.0
  port: 27017

storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true

// ๋ ˆํ”Œ๋ฆฌ์นด ์…‹ ์ดˆ๊ธฐํ™” (Primary ๋…ธ๋“œ์—์„œ)
rs.initiate({
  _id: "myReplicaSet",
  members: [
    { _id: 0, host: "mongodb1.example.com:27017" },
    { _id: 1, host: "mongodb2.example.com:27017" },
    { _id: 2, host: "mongodb3.example.com:27017" }
  ]
})

// ์ƒํƒœ ํ™•์ธ
rs.status()
2๋‹จ๊ณ„: ์ƒค๋”ฉ ํด๋Ÿฌ์Šคํ„ฐ ๊ตฌ์„ฑ

๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฌ๋‹ค๋ฉด ์ƒค๋”ฉ์ด ํ•„์ˆ˜์•ผ!
// Config Server ์‹œ์ž‘ (3๊ฐœ ๊ถŒ์žฅ)
mongod --configsvr --replSet configReplSet --port 27019

// Mongos (์ฟผ๋ฆฌ ๋ผ์šฐํ„ฐ) ์‹œ์ž‘
mongos --configdb configReplSet/config1:27019,config2:27019,config3:27019

// Shard ์ถ”๊ฐ€
sh.addShard("shard1/mongodb4:27017,mongodb5:27017,mongodb6:27017")
sh.addShard("shard2/mongodb7:27017,mongodb8:27017,mongodb9:27017")

// ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ƒค๋”ฉ ํ™œ์„ฑํ™”
sh.enableSharding("myDatabase")

// ์ปฌ๋ ‰์…˜ ์ƒค๋”ฉ (ํ•ด์‹œ ๊ธฐ๋ฐ˜)
sh.shardCollection("myDatabase.users", { userId: "hashed" })

// ๋˜๋Š” ๋ฒ”์œ„ ๊ธฐ๋ฐ˜ ์ƒค๋”ฉ
sh.shardCollection("myDatabase.orders", { customerId: 1, orderDate: 1 })
3๋‹จ๊ณ„: ๋ณด์•ˆ ์„ค์ •
// ์ธ์ฆ ํ™œ์„ฑํ™”
security:
  authorization: enabled
  keyFile: /path/to/keyfile

// ๊ด€๋ฆฌ์ž ๊ณ„์ • ์ƒ์„ฑ
use admin
db.createUser({
  user: "admin",
  pwd: "securePassword123!",
  roles: [ { role: "root", db: "admin" } ]
})

// ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‚ฌ์šฉ์ž ์ƒ์„ฑ
use myDatabase
db.createUser({
  user: "appUser",
  pwd: "appPassword456!",
  roles: [ 
    { role: "readWrite", db: "myDatabase" },
    { role: "read", db: "analytics" }
  ]
})
๐ŸŒŸ Cassandra ํด๋Ÿฌ์Šคํ„ฐ ๊ตฌ์ถ•ํ•˜๊ธฐ
1๋‹จ๊ณ„: ๋…ธ๋“œ ์„ค์ •

Cassandra๋Š” ๋ชจ๋“  ๋…ธ๋“œ๊ฐ€ ๋™๋“ฑํ•˜๋ฏ€๋กœ ๊ฐ ๋…ธ๋“œ์— ๋™์ผํ•œ ์„ค์ •์„ ์ ์šฉํ•ด.
# cassandra.yaml ์ฃผ์š” ์„ค์ •
cluster_name: 'MyCluster'

# Seed ๋…ธ๋“œ ์ง€์ • (ํด๋Ÿฌ์Šคํ„ฐ ๋ฐœ๊ฒฌ์šฉ)
seed_provider:
  - class_name: org.apache.cassandra.locator.SimpleSeedProvider
    parameters:
      - seeds: "192.168.1.10,192.168.1.11,192.168.1.12"

# ๋…ธ๋“œ ๊ฐ„ ํ†ต์‹ 
listen_address: 192.168.1.10
rpc_address: 0.0.0.0

# ๋ฐ์ดํ„ฐ ๋””๋ ‰ํ† ๋ฆฌ
data_file_directories:
  - /var/lib/cassandra/data

commitlog_directory: /var/lib/cassandra/commitlog

# ์Šค๋‹ˆ์น˜ ์„ค์ • (๋„คํŠธ์›Œํฌ ํ† ํด๋กœ์ง€)
endpoint_snitch: GossipingPropertyFileSnitch
2๋‹จ๊ณ„: ํด๋Ÿฌ์Šคํ„ฐ ๊ตฌ์„ฑ
# ์ฒซ ๋ฒˆ์งธ ๋…ธ๋“œ ์‹œ์ž‘
cassandra -R

# ๋‹ค๋ฅธ ๋…ธ๋“œ๋“ค ์ˆœ์ฐจ์ ์œผ๋กœ ์‹œ์ž‘
# ๊ฐ ๋…ธ๋“œ๊ฐ€ ์ž๋™์œผ๋กœ ํด๋Ÿฌ์Šคํ„ฐ์— ์กฐ์ธ๋จ

# ํด๋Ÿฌ์Šคํ„ฐ ์ƒํƒœ ํ™•์ธ
nodetool status

# ์ถœ๋ ฅ ์˜ˆ์‹œ:
# Datacenter: dc1
# Status=Up/Down
# State=Normal/Leaving/Joining/Moving
# --  Address        Load       Tokens  Owns    Host ID
# UN  192.168.1.10   1.2 TB     256     33.3%   abc123...
# UN  192.168.1.11   1.1 TB     256     33.4%   def456...
# UN  192.168.1.12   1.3 TB     256     33.3%   ghi789...
3๋‹จ๊ณ„: Keyspace ๋ฐ ํ…Œ์ด๋ธ” ์ƒ์„ฑ
// CQL Shell ์ ‘์†
cqlsh

// Keyspace ์ƒ์„ฑ
CREATE KEYSPACE my_app WITH replication = {
  'class': 'NetworkTopologyStrategy',
  'dc1': 3
} AND durable_writes = true;

// ์‚ฌ์šฉ์ž ํ…Œ์ด๋ธ”
CREATE TABLE my_app.users (
  user_id uuid PRIMARY KEY,
  username text,
  email text,
  created_at timestamp,
  last_login timestamp
);

// ์‚ฌ์šฉ์ž ํ™œ๋™ ๋กœ๊ทธ (์‹œ๊ณ„์—ด)
CREATE TABLE my_app.user_activity (
  user_id uuid,
  activity_date date,
  activity_time timestamp,
  activity_type text,
  details map<text, text>,
  PRIMARY KEY ((user_id, activity_date), activity_time)
) WITH CLUSTERING ORDER BY (activity_time DESC)
  AND compaction = {
    'class': 'TimeWindowCompactionStrategy',
    'compaction_window_unit': 'DAYS',
    'compaction_window_size': 1
  }
  AND default_time_to_live = 2592000;  // 30์ผ ํ›„ ์ž๋™ ์‚ญ์ œ
4๋‹จ๊ณ„: ๋ณด์•ˆ ์„ค์ •
# cassandra.yaml์— ์ธ์ฆ ํ™œ์„ฑํ™”
authenticator: PasswordAuthenticator
authorizer: CassandraAuthorizer

# ๊ธฐ๋ณธ cassandra ๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธ ํ›„ ์ƒˆ ๊ด€๋ฆฌ์ž ์ƒ์„ฑ
CREATE ROLE admin WITH PASSWORD = 'securePassword123!' 
  AND SUPERUSER = true 
  AND LOGIN = true;

# ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‚ฌ์šฉ์ž ์ƒ์„ฑ
CREATE ROLE app_user WITH PASSWORD = 'appPassword456!' 
  AND LOGIN = true;

GRANT ALL PERMISSIONS ON KEYSPACE my_app TO app_user;
๐Ÿ’ก ์šด์˜ ํŒ: ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ๋ฐ˜๋“œ์‹œ ๋ชจ๋‹ˆํ„ฐ๋ง ๋„๊ตฌ๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•ด! MongoDB๋Š” MongoDB Atlas๋‚˜ Ops Manager, Cassandra๋Š” DataStax OpsCenter๋‚˜ Prometheus + Grafana ์กฐํ•ฉ์„ ์ถ”์ฒœํ•ด. ๐Ÿ“Š
## ๐Ÿ’ป ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์—ฐ๋™: ์ฝ”๋“œ๋กœ ๋ณด๋Š” ์‹ค์ „ ์˜ˆ์ œ ์ด์ œ ์‹ค์ œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์ฝ”๋“œ๋กœ ์•Œ์•„๋ณด์ž! Node.js ์˜ˆ์ œ๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ์„ค๋ช…ํ• ๊ฒŒ. ๐Ÿ–ฅ๏ธ

๐Ÿƒ MongoDB ์—ฐ๋™ (Node.js)
์„ค์น˜ ๋ฐ ์—ฐ๊ฒฐ:
// npm install mongodb
const { MongoClient } = require('mongodb');

const uri = "mongodb://username:password@mongodb1:27017,mongodb2:27017,mongodb3:27017/myDatabase?replicaSet=myReplicaSet";
const client = new MongoClient(uri, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
  maxPoolSize: 50,
  wtimeoutMS: 2500
});

async function connectDB() {
  try {
    await client.connect();
    console.log("MongoDB ์—ฐ๊ฒฐ ์„ฑ๊ณต!");
    return client.db("myDatabase");
  } catch (error) {
    console.error("์—ฐ๊ฒฐ ์‹คํŒจ:", error);
    throw error;
  }
}
CRUD ์ž‘์—…:
const db = await connectDB();
const usersCollection = db.collection('users');

// Create - ์‚ฌ์šฉ์ž ์ƒ์„ฑ
async function createUser(userData) {
  const result = await usersCollection.insertOne({
    username: userData.username,
    email: userData.email,
    profile: {
      firstName: userData.firstName,
      lastName: userData.lastName,
      age: userData.age
    },
    createdAt: new Date(),
    tags: userData.tags || []
  });
  return result.insertedId;
}

// Read - ์‚ฌ์šฉ์ž ์กฐํšŒ
async function findUserByEmail(email) {
  return await usersCollection.findOne({ email: email });
}

// Read - ๋ณต์žกํ•œ ์ฟผ๋ฆฌ
async function findActiveUsers(minAge) {
  return await usersCollection.find({
    'profile.age': { $gte: minAge },
    status: 'active',
    lastLogin: { $gte: new Date(Date.now() - 30*24*60*60*1000) }
  })
  .sort({ lastLogin: -1 })
  .limit(100)
  .toArray();
}

// Update - ์‚ฌ์šฉ์ž ์ •๋ณด ์ˆ˜์ •
async function updateUserProfile(userId, updates) {
  return await usersCollection.updateOne(
    { _id: userId },
    { 
      $set: { 
        'profile.firstName': updates.firstName,
        'profile.lastName': updates.lastName,
        updatedAt: new Date()
      },
      $push: { tags: updates.newTag }
    }
  );
}

// Delete - ์‚ฌ์šฉ์ž ์‚ญ์ œ
async function deleteUser(userId) {
  return await usersCollection.deleteOne({ _id: userId });
}

// ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ - ํ†ต๊ณ„ ๋ถ„์„
async function getUserStatsByAge() {
  return await usersCollection.aggregate([
    {
      $match: { status: 'active' }
    },
    {
      $group: {
        _id: {
          $floor: { $divide: ['$profile.age', 10] }
        },
        count: { $sum: 1 },
        avgAge: { $avg: '$profile.age' }
      }
    },
    {
      $project: {
        ageGroup: { $multiply: ['$_id', 10] },
        count: 1,
        avgAge: { $round: ['$avgAge', 1] }
      }
    },
    {
      $sort: { ageGroup: 1 }
    }
  ]).toArray();
}
ํŠธ๋žœ์žญ์…˜ ์‚ฌ์šฉ:
// MongoDB 4.0+ ์—์„œ ๋‹ค์ค‘ ๋ฌธ์„œ ํŠธ๋žœ์žญ์…˜ ์ง€์›
async function transferPoints(fromUserId, toUserId, points) {
  const session = client.startSession();
  
  try {
    await session.withTransaction(async () => {
      const usersCollection = db.collection('users');
      
      // ํฌ์ธํŠธ ์ฐจ๊ฐ
      await usersCollection.updateOne(
        { _id: fromUserId },
        { $inc: { points: -points } },
        { session }
      );
      
      // ํฌ์ธํŠธ ์ถ”๊ฐ€
      await usersCollection.updateOne(
        { _id: toUserId },
        { $inc: { points: points } },
        { session }
      );
      
      // ๊ฑฐ๋ž˜ ๊ธฐ๋ก
      const transactionsCollection = db.collection('transactions');
      await transactionsCollection.insertOne({
        fromUser: fromUserId,
        toUser: toUserId,
        amount: points,
        timestamp: new Date()
      }, { session });
    });
    
    console.log("ํŠธ๋žœ์žญ์…˜ ์„ฑ๊ณต!");
  } catch (error) {
    console.error("ํŠธ๋žœ์žญ์…˜ ์‹คํŒจ:", error);
    throw error;
  } finally {
    await session.endSession();
  }
}
๐ŸŒŸ Cassandra ์—ฐ๋™ (Node.js)
์„ค์น˜ ๋ฐ ์—ฐ๊ฒฐ:
// npm install cassandra-driver
const cassandra = require('cassandra-driver');

const client = new cassandra.Client({
  contactPoints: ['192.168.1.10', '192.168.1.11', '192.168.1.12'],
  localDataCenter: 'dc1',
  keyspace: 'my_app',
  credentials: {
    username: 'app_user',
    password: 'appPassword456!'
  },
  pooling: {
    coreConnectionsPerHost: {
      [cassandra.types.distance.local]: 2,
      [cassandra.types.distance.remote]: 1
    }
  }
});

async function connectCassandra() {
  try {
    await client.connect();
    console.log("Cassandra ์—ฐ๊ฒฐ ์„ฑ๊ณต!");
  } catch (error) {
    console.error("์—ฐ๊ฒฐ ์‹คํŒจ:", error);
    throw error;
  }
}
CRUD ์ž‘์—…:
// Create - ์‚ฌ์šฉ์ž ์ƒ์„ฑ
async function createUser(userData) {
  const query = `
    INSERT INTO users (user_id, username, email, created_at)
    VALUES (?, ?, ?, ?)
  `;
  const params = [
    cassandra.types.Uuid.random(),
    userData.username,
    userData.email,
    new Date()
  ];
  
  await client.execute(query, params, { prepare: true });
}

// Read - ์‚ฌ์šฉ์ž ์กฐํšŒ
async function getUserById(userId) {
  const query = 'SELECT * FROM users WHERE user_id = ?';
  const result = await client.execute(query, [userId], { prepare: true });
  return result.rows[0];
}

// ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ ์‚ฝ์ž…
async function logUserActivity(userId, activityType, details) {
  const query = `
    INSERT INTO user_activity 
    (user_id, activity_date, activity_time, activity_type, details)
    VALUES (?, ?, ?, ?, ?)
  `;
  const now = new Date();
  const params = [
    userId,
    cassandra.types.LocalDate.fromDate(now),
    now,
    activityType,
    details
  ];
  
  await client.execute(query, params, { prepare: true });
}

// ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ ์กฐํšŒ
async function getUserActivityToday(userId) {
  const query = `
    SELECT * FROM user_activity
    WHERE user_id = ? AND activity_date = ?
    ORDER BY activity_time DESC
    LIMIT 100
  `;
  const today = cassandra.types.LocalDate.fromDate(new Date());
  const result = await client.execute(
    query, 
    [userId, today], 
    { prepare: true }
  );
  return result.rows;
}

// ๋ฐฐ์น˜ ์ž‘์—…
async function batchInsertActivities(activities) {
  const queries = activities.map(activity => ({
    query: `
      INSERT INTO user_activity 
      (user_id, activity_date, activity_time, activity_type, details)
      VALUES (?, ?, ?, ?, ?)
    `,
    params: [
      activity.userId,
      cassandra.types.LocalDate.fromDate(activity.timestamp),
      activity.timestamp,
      activity.type,
      activity.details
    ]
  }));
  
  await client.batch(queries, { prepare: true });
}

// ์ผ๊ด€์„ฑ ๋ ˆ๋ฒจ ์ง€์ •
async function criticalRead(userId) {
  const query = 'SELECT * FROM users WHERE user_id = ?';
  const result = await client.execute(
    query, 
    [userId], 
    { 
      prepare: true,
      consistency: cassandra.types.consistencies.quorum
    }
  );
  return result.rows[0];
}
โš ๏ธ ์„ฑ๋Šฅ ์ตœ์ ํ™” ์ฃผ์˜์‚ฌํ•ญ: โ€ข Prepared Statements ์‚ฌ์šฉ: prepare: true ์˜ต์…˜์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ๋ฏธ๋ฆฌ ์ปดํŒŒ์ผํ•˜๋ฉด ์„ฑ๋Šฅ์ด ํฌ๊ฒŒ ํ–ฅ์ƒ๋ผ!
โ€ข Connection Pooling: ์—ฐ๊ฒฐ ํ’€์„ ์ ์ ˆํžˆ ์„ค์ •ํ•ด์„œ ์žฌ์‚ฌ์šฉํ•ด์•ผ ํ•ด.
โ€ข ๋ฐฐ์น˜ ์ž‘์—…: ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์‚ฝ์ž…/์ˆ˜์ • ์ž‘์—…์€ ๋ฐฐ์น˜๋กœ ๋ฌถ์–ด์„œ ์ฒ˜๋ฆฌํ•˜๋ฉด ํšจ์œจ์ ์ด์•ผ.
โ€ข ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ: async/await๋ฅผ ํ™œ์šฉํ•ด์„œ ๋…ผ๋ธ”๋กœํ‚น ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ด.
## ๐Ÿ“ˆ ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ํŠœ๋‹ ์ „๋žต ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ตฌ์ถ•ํ–ˆ๋‹ค๊ณ  ๋์ด ์•„๋‹ˆ์•ผ! ์ง€์†์ ์ธ ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ํŠœ๋‹์ด ํ•„์š”ํ•ด. ๐Ÿ”

๐Ÿƒ MongoDB ๋ชจ๋‹ˆํ„ฐ๋ง
์ฃผ์š” ๋ชจ๋‹ˆํ„ฐ๋ง ์ง€ํ‘œ:

1. ์—ฐ๊ฒฐ ๋ฐ ์ž‘์—… ํ†ต๊ณ„ โ€ข Current Connections: ํ˜„์žฌ ํ™œ์„ฑ ์—ฐ๊ฒฐ ์ˆ˜
โ€ข Operations per Second: ์ดˆ๋‹น ์ž‘์—… ์ˆ˜ (์ฝ๊ธฐ/์“ฐ๊ธฐ)
โ€ข Queue Length: ๋Œ€๊ธฐ ์ค‘์ธ ์ž‘์—… ์ˆ˜

2. ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰

โ€ข Resident Memory: ์‹ค์ œ ์‚ฌ์šฉ ์ค‘์ธ ๋ฉ”๋ชจ๋ฆฌ
โ€ข Virtual Memory: ๊ฐ€์ƒ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰
โ€ข Page Faults: ํŽ˜์ด์ง€ ํดํŠธ ๋ฐœ์ƒ ํšŸ์ˆ˜

3. ๋ณต์ œ ์ง€์—ฐ

โ€ข Replication Lag: Primary์™€ Secondary ๊ฐ„ ์ง€์—ฐ ์‹œ๊ฐ„
โ€ข Oplog Window: Oplog๊ฐ€ ์ปค๋ฒ„ํ•˜๋Š” ์‹œ๊ฐ„ ๋ฒ”์œ„
๋ชจ๋‹ˆํ„ฐ๋ง ๋ช…๋ น์–ด:
// ์„œ๋ฒ„ ์ƒํƒœ ํ™•์ธ
db.serverStatus()

// ํ˜„์žฌ ์ž‘์—… ํ™•์ธ
db.currentOp()

// ๋А๋ฆฐ ์ฟผ๋ฆฌ ํ”„๋กœํŒŒ์ผ๋ง
db.setProfilingLevel(1, { slowms: 100 })  // 100ms ์ด์ƒ ์ฟผ๋ฆฌ ๊ธฐ๋ก
db.system.profile.find().sort({ ts: -1 }).limit(10)

// ์ธ๋ฑ์Šค ์‚ฌ์šฉ ํ†ต๊ณ„
db.collection.aggregate([{ $indexStats: {} }])

// ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ†ต๊ณ„
db.stats()

// ์ปฌ๋ ‰์…˜ ํ†ต๊ณ„
db.collection.stats()
์„ฑ๋Šฅ ํŠœ๋‹ ์ฒดํฌ๋ฆฌ์ŠคํŠธ:

โœ… ์ธ๋ฑ์Šค ์ตœ์ ํ™”
โ€ข ์ž์ฃผ ์กฐํšŒ๋˜๋Š” ํ•„๋“œ์— ์ธ๋ฑ์Šค ์ƒ์„ฑ
โ€ข ๋ณตํ•ฉ ์ธ๋ฑ์Šค ์ˆœ์„œ ์ตœ์ ํ™” (์„ ํƒ๋„๊ฐ€ ๋†’์€ ํ•„๋“œ๋ฅผ ์•ž์—)
โ€ข ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ธ๋ฑ์Šค ์ œ๊ฑฐ
โ€ข ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค ํ™œ์šฉ (์ฟผ๋ฆฌ๊ฐ€ ์ธ๋ฑ์Šค๋งŒ์œผ๋กœ ์ฒ˜๋ฆฌ)

โœ… ์ฟผ๋ฆฌ ์ตœ์ ํ™”
โ€ข explain()๋กœ ์‹คํ–‰ ๊ณ„ํš ๋ถ„์„
โ€ข ํ•„์š”ํ•œ ํ•„๋“œ๋งŒ ํ”„๋กœ์ ์…˜
โ€ข ์ •๊ทœํ‘œํ˜„์‹ ์‚ฌ์šฉ ์ตœ์†Œํ™”
โ€ข $or ๋Œ€์‹  $in ์‚ฌ์šฉ ๊ณ ๋ ค

โœ… ํ•˜๋“œ์›จ์–ด ๋ฐ ์„ค์ •
โ€ข ์ถฉ๋ถ„ํ•œ RAM ํ™•๋ณด (Working Set์ด ๋ฉ”๋ชจ๋ฆฌ์— ๋“ค์–ด๊ฐ€๋„๋ก)
โ€ข SSD ์‚ฌ์šฉ ๊ถŒ์žฅ
โ€ข WiredTiger ์บ์‹œ ํฌ๊ธฐ ์กฐ์ •
โ€ข ์ ์ ˆํ•œ Read/Write Concern ์„ค์ •

๐ŸŒŸ Cassandra ๋ชจ๋‹ˆํ„ฐ๋ง
์ฃผ์š” ๋ชจ๋‹ˆํ„ฐ๋ง ์ง€ํ‘œ:

1. ๋…ธ๋“œ ์ƒํƒœ โ€ข Node Status: UP/DOWN ์ƒํƒœ
โ€ข Load: ๊ฐ ๋…ธ๋“œ์˜ ๋ฐ์ดํ„ฐ ํฌ๊ธฐ
โ€ข Ownership: ํ† ํฐ ๋ฒ”์œ„ ์†Œ์œ  ๋น„์œจ

2. ์ฝ๊ธฐ/์“ฐ๊ธฐ ์„ฑ๋Šฅ

โ€ข Read Latency: ์ฝ๊ธฐ ์ง€์—ฐ ์‹œ๊ฐ„
โ€ข Write Latency: ์“ฐ๊ธฐ ์ง€์—ฐ ์‹œ๊ฐ„
โ€ข Throughput: ์ดˆ๋‹น ์ฒ˜๋ฆฌ๋Ÿ‰

3. Compaction ๋ฐ GC

โ€ข Pending Compactions: ๋Œ€๊ธฐ ์ค‘์ธ Compaction
โ€ข GC Pause Time: ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ์ผ์‹œ์ •์ง€ ์‹œ๊ฐ„
โ€ข Heap Memory Usage: ํž™ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋ฅ 
๋ชจ๋‹ˆํ„ฐ๋ง ๋ช…๋ น์–ด:
# ํด๋Ÿฌ์Šคํ„ฐ ์ƒํƒœ
nodetool status

# ๋…ธ๋“œ ์ •๋ณด
nodetool info

# ์„ฑ๋Šฅ ํ†ต๊ณ„
nodetool tablestats my_app.users

# Compaction ์ƒํƒœ
nodetool compactionstats

# ํ”„๋ก์‹œ ํžˆ์Šคํ† ๊ทธ๋žจ (์ง€์—ฐ ์‹œ๊ฐ„ ๋ถ„ํฌ)
nodetool proxyhistograms

# ์Šค๋ ˆ๋“œํ’€ ์ƒํƒœ
nodetool tpstats

# GC ํ†ต๊ณ„
nodetool gcstats

# ํŠน์ • ํ…Œ์ด๋ธ” ํ”Œ๋Ÿฌ์‹œ
nodetool flush my_app users
์„ฑ๋Šฅ ํŠœ๋‹ ์ฒดํฌ๋ฆฌ์ŠคํŠธ:

โœ… ๋ฐ์ดํ„ฐ ๋ชจ๋ธ ์ตœ์ ํ™”
โ€ข ์ฟผ๋ฆฌ ํŒจํ„ด์— ๋งž๋Š” ํŒŒํ‹ฐ์…˜ ํ‚ค ์„ค๊ณ„
โ€ข ํŒŒํ‹ฐ์…˜ ํฌ๊ธฐ 100MB ์ดํ•˜ ์œ ์ง€
โ€ข ์ ์ ˆํ•œ Clustering Key๋กœ ์ •๋ ฌ ์ตœ์ ํ™”
โ€ข ํ•„์š”์‹œ ๋น„์ •๊ทœํ™”๋กœ ์กฐ์ธ ํšŒํ”ผ

โœ… Compaction ์ „๋žต
โ€ข ์›Œํฌ๋กœ๋“œ์— ๋งž๋Š” Compaction ์ „๋žต ์„ ํƒ
โ€ข ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ๋Š” TWCS ์‚ฌ์šฉ
โ€ข Compaction ์Šค์ผ€์ค„ ์กฐ์ •

โœ… ํ•˜๋“œ์›จ์–ด ๋ฐ JVM ์„ค์ •
โ€ข ์ถฉ๋ถ„ํ•œ RAM (์ตœ์†Œ 8GB, ๊ถŒ์žฅ 32GB+)
โ€ข SSD ์‚ฌ์šฉ ํ•„์ˆ˜
โ€ข JVM ํž™ ํฌ๊ธฐ ์กฐ์ • (๋ฌผ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ์˜ 1/4 ~ 1/2)
โ€ข G1GC ์‚ฌ์šฉ ๊ถŒ์žฅ

โœ… ์ผ๊ด€์„ฑ ๋ฐ ๋ณต์ œ
โ€ข ์ ์ ˆํ•œ ๋ณต์ œ ๊ณ„์ˆ˜ ์„ค์ • (์ผ๋ฐ˜์ ์œผ๋กœ 3)
โ€ข ์ผ๊ด€์„ฑ ๋ ˆ๋ฒจ ์ตœ์ ํ™”
โ€ข Hinted Handoff ํ™œ์šฉ

์„ฑ๋Šฅ ์ตœ์ ํ™” ์ „๋žต ๋น„๊ต MongoDB ์ตœ์ ํ™” ์ธ๋ฑ์Šค ์ „๋žต ๋ณตํ•ฉ ์ธ๋ฑ์Šค ํ™œ์šฉ ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค ๊ตฌํ˜„ ์ธ๋ฑ์Šค ๊ต์ฐจ ์ตœ์†Œํ™” ์ฟผ๋ฆฌ ์ตœ์ ํ™” Projection์œผ๋กœ ํ•„๋“œ ์ œํ•œ ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ ํ™œ์šฉ explain() ๋ถ„์„ ์‹œ์Šคํ…œ ์„ค์ • WiredTiger ์บ์‹œ ์กฐ์ • ์ ์ ˆํ•œ Write Concern ์ƒค๋”ฉ ํ‚ค ์ตœ์ ํ™” Cassandra ์ตœ์ ํ™” ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง ์ฟผ๋ฆฌ ์ค‘์‹ฌ ์„ค๊ณ„ ํŒŒํ‹ฐ์…˜ ํฌ๊ธฐ ๊ด€๋ฆฌ ๋น„์ •๊ทœํ™” ์ ์šฉ Compaction ์ ์ ˆํ•œ ์ „๋žต ์„ ํƒ TWCS for ์‹œ๊ณ„์—ด ์Šค์ผ€์ค„ ์ตœ์ ํ™” ์‹œ์Šคํ…œ ํŠœ๋‹ JVM ํž™ ํฌ๊ธฐ ์กฐ์ • ์ผ๊ด€์„ฑ ๋ ˆ๋ฒจ ์ตœ์ ํ™” ๋ณต์ œ ๊ณ„์ˆ˜ ์„ค์ • ๊ณตํ†ต: ์ถฉ๋ถ„ํ•œ RAM, SSD ์‚ฌ์šฉ, ์ง€์†์ ์ธ ๋ชจ๋‹ˆํ„ฐ๋ง
## ๐ŸŽ“ ์‹ค๋ฌด์—์„œ ๋ฐฐ์šด ๊ตํ›ˆ๊ณผ ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค ์ด๋ก ๊ณผ ์‹ค์ „์€ ๋‹ค๋ฅด์ง€! ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ ๊ฒช์€ ๊ฒฝํ—˜์„ ๋ฐ”ํƒ•์œผ๋กœ ์ค‘์š”ํ•œ ๊ตํ›ˆ๋“ค์„ ๊ณต์œ ํ• ๊ฒŒ. ๐Ÿ’ก

โŒ ํ”ํ•œ ์‹ค์ˆ˜ 1: ์ž˜๋ชป๋œ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง MongoDB: ๋ชจ๋“  ๊ฒƒ์„ ์ž„๋ฒ ๋”ฉํ•˜๊ฑฐ๋‚˜ ๋ชจ๋“  ๊ฒƒ์„ ์ฐธ์กฐ๋กœ ์ฒ˜๋ฆฌ
ํ•ด๊ฒฐ: ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ํŒจํ„ด์„ ๋ถ„์„ํ•ด์„œ ์ ์ ˆํžˆ ํ˜ผํ•ฉ ์‚ฌ์šฉ. 1:N ๊ด€๊ณ„์—์„œ N์ด ์ž‘์œผ๋ฉด ์ž„๋ฒ ๋”ฉ, ํฌ๋ฉด ์ฐธ์กฐ!

Cassandra: RDBMS ์‚ฌ๊ณ ๋ฐฉ์‹์œผ๋กœ ์ •๊ทœํ™”๋œ ํ…Œ์ด๋ธ” ์„ค๊ณ„
ํ•ด๊ฒฐ: ์ฟผ๋ฆฌ ํŒจํ„ด์„ ๋จผ์ € ์ •์˜ํ•˜๊ณ , ๊ฐ ์ฟผ๋ฆฌ๋งˆ๋‹ค ์ตœ์ ํ™”๋œ ํ…Œ์ด๋ธ” ์ƒ์„ฑ. ์ค‘๋ณต ์ €์žฅ์„ ๋‘๋ ค์›Œํ•˜์ง€ ๋ง ๊ฒƒ!
โŒ ํ”ํ•œ ์‹ค์ˆ˜ 2: ์ธ๋ฑ์Šค ๊ณผ๋‹ค ๋˜๋Š” ๋ถ€์กฑ

๋ฌธ์ œ: ๋ชจ๋“  ํ•„๋“œ์— ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“ค๊ฑฐ๋‚˜, ๋ฐ˜๋Œ€๋กœ ์ธ๋ฑ์Šค๋ฅผ ์ „ํ˜€ ๋งŒ๋“ค์ง€ ์•Š์Œ
ํ•ด๊ฒฐ: ์‹ค์ œ ์ฟผ๋ฆฌ ํŒจํ„ด์„ ๋ถ„์„ํ•ด์„œ ํ•„์š”ํ•œ ์ธ๋ฑ์Šค๋งŒ ์ƒ์„ฑ. ์“ฐ๊ธฐ ์„ฑ๋Šฅ๊ณผ ์ฝ๊ธฐ ์„ฑ๋Šฅ์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ๊ณ ๋ ค!

// ์ข‹์€ ์˜ˆ: ์ž์ฃผ ์กฐํšŒ๋˜๋Š” ํ•„๋“œ ์กฐํ•ฉ
db.orders.createIndex({ customerId: 1, orderDate: -1 })

// ๋‚˜์œ ์˜ˆ: ๊ฑฐ์˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํ•„๋“œ
db.orders.createIndex({ internalNotes: 1 })  // ๋ถˆํ•„์š”!
โŒ ํ”ํ•œ ์‹ค์ˆ˜ 3: ๋ถ€์ ์ ˆํ•œ ์ƒค๋”ฉ/ํŒŒํ‹ฐ์…˜ ํ‚ค ์„ ํƒ MongoDB: ์ˆœ์ฐจ์ ์œผ๋กœ ์ฆ๊ฐ€ํ•˜๋Š” ๊ฐ’์„ ์ƒค๋“œ ํ‚ค๋กœ ์‚ฌ์šฉ (์˜ˆ: timestamp, auto-increment ID)
๋ฌธ์ œ: ํ•ซ์ŠคํŒŸ ๋ฐœ์ƒ! ๋ชจ๋“  ์“ฐ๊ธฐ๊ฐ€ ํ•˜๋‚˜์˜ ์ƒค๋“œ๋กœ ์ง‘์ค‘
ํ•ด๊ฒฐ: ํ•ด์‹œ ์ƒค๋”ฉ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, ๋ณตํ•ฉ ์ƒค๋“œ ํ‚ค๋กœ ๋ถ„์‚ฐ

Cassandra: ์นด๋””๋„๋ฆฌํ‹ฐ๊ฐ€ ๋‚ฎ์€ ํ•„๋“œ๋ฅผ ํŒŒํ‹ฐ์…˜ ํ‚ค๋กœ ์‚ฌ์šฉ (์˜ˆ: status, type)
๋ฌธ์ œ: ์†Œ์ˆ˜์˜ ๊ฑฐ๋Œ€ํ•œ ํŒŒํ‹ฐ์…˜ ์ƒ์„ฑ
ํ•ด๊ฒฐ: ์นด๋””๋„๋ฆฌํ‹ฐ๊ฐ€ ๋†’์€ ํ•„๋“œ ์‚ฌ์šฉ (์˜ˆ: user_id, sensor_id)
โœ… ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค 1: ๋ฐฑ์—… ์ „๋žต MongoDB:
โ€ข mongodump/mongorestore ์‚ฌ์šฉ (์†Œ๊ทœ๋ชจ)
โ€ข ํŒŒ์ผ์‹œ์Šคํ…œ ์Šค๋ƒ…์ƒท ํ™œ์šฉ (๋Œ€๊ทœ๋ชจ)
โ€ข Oplog ๊ธฐ๋ฐ˜ Point-in-Time ๋ณต๊ตฌ
โ€ข ์ •๊ธฐ์ ์ธ ๋ฐฑ์—… ํ…Œ์ŠคํŠธ ํ•„์ˆ˜!

Cassandra:
โ€ข nodetool snapshot์œผ๋กœ ์Šค๋ƒ…์ƒท ์ƒ์„ฑ
โ€ข ์ฆ๋ถ„ ๋ฐฑ์—… ํ™œ์šฉ
โ€ข ๋‹ค์ค‘ ๋ฐ์ดํ„ฐ์„ผํ„ฐ ๋ณต์ œ๋กœ ์žฌํ•ด ๋ณต๊ตฌ
โ€ข ์ฃผ๊ธฐ์ ์ธ ๋ณต๊ตฌ ํ›ˆ๋ จ
โœ… ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค 2: ๋ณด์•ˆ ๊ฐ•ํ™” โ€ข ์ธ์ฆ ๋ฐ ๊ถŒํ•œ ๊ด€๋ฆฌ ํ™œ์„ฑํ™”
โ€ข TLS/SSL ์•”ํ˜ธํ™” ํ†ต์‹ 
โ€ข ๋„คํŠธ์›Œํฌ ๊ฒฉ๋ฆฌ (VPC, ๋ฐฉํ™”๋ฒฝ)
โ€ข ์ •๊ธฐ์ ์ธ ๋ณด์•ˆ ํŒจ์น˜
โ€ข ๊ฐ์‚ฌ ๋กœ๊ทธ ํ™œ์„ฑํ™”
โ€ข ์ตœ์†Œ ๊ถŒํ•œ ์›์น™ ์ ์šฉ
โ€ข ๋น„๋ฐ€๋ฒˆํ˜ธ ์ •์ฑ… ๊ฐ•ํ™”
โœ… ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค 3: ์šฉ๋Ÿ‰ ๊ณ„ํš โ€ข ๋ฐ์ดํ„ฐ ์ฆ๊ฐ€์œจ ์˜ˆ์ธก
โ€ข ํ”ผํฌ ์‹œ๊ฐ„๋Œ€ ํŠธ๋ž˜ํ”ฝ ๋ถ„์„
โ€ข ์—ฌ์œ  ์šฉ๋Ÿ‰ ํ™•๋ณด (์ตœ์†Œ 30%)
โ€ข ์ž๋™ ์Šค์ผ€์ผ๋ง ์„ค์ •
โ€ข ์ •๊ธฐ์ ์ธ ์šฉ๋Ÿ‰ ๋ฆฌ๋ทฐ
โ€ข ์•„์นด์ด๋น™ ์ „๋žต ์ˆ˜๋ฆฝ
๐Ÿ’ก ์žฌ๋Šฅ๋„ท ํ™œ์šฉ ํŒ: NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ตฌ์ถ•์ด๋‚˜ ์ตœ์ ํ™”๊ฐ€ ์–ด๋ ต๋‹ค๋ฉด, ์žฌ๋Šฅ๋„ท(https://www.jaenung.net)์—์„œ ์ „๋ฌธ๊ฐ€์˜ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด! ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค๊ณ„, ์„ฑ๋Šฅ ํŠœ๋‹, ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋“ฑ ๋‹ค์–‘ํ•œ ์žฌ๋Šฅ์„ ๊ฐ€์ง„ ์ „๋ฌธ๊ฐ€๋“ค์ด ์žˆ์œผ๋‹ˆ๊นŒ ํ™œ์šฉํ•ด๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ. ๐Ÿค
## ๐Ÿš€ ๋ฏธ๋ž˜ ํŠธ๋ Œ๋“œ์™€ ๋ฐœ์ „ ๋ฐฉํ–ฅ NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ฏธ๋ž˜๋Š” ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ์ตœ์‹  ํŠธ๋ Œ๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž! ๐Ÿ”ฎ

๐ŸŒŸ MongoDB์˜ ์ง„ํ™”
1. ๋ฉ€ํ‹ฐ ํด๋ผ์šฐ๋“œ ์ง€์› ๊ฐ•ํ™”

MongoDB Atlas๋Š” AWS, Azure, GCP๋ฅผ ๋„˜๋‚˜๋“ค๋ฉฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด. ํด๋ผ์šฐ๋“œ ๋ฒค๋” ์ข…์†์„ ํ”ผํ•˜๊ณ  ์ตœ์ ์˜ ํ™˜๊ฒฝ์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์ง€!

2. ์„œ๋ฒ„๋ฆฌ์Šค ์ธ์Šคํ„ด์Šค

์‚ฌ์šฉํ•œ ๋งŒํผ๋งŒ ๋น„์šฉ์„ ์ง€๋ถˆํ•˜๋Š” ์„œ๋ฒ„๋ฆฌ์Šค MongoDB๊ฐ€ ๋“ฑ์žฅํ–ˆ์–ด. ํŠธ๋ž˜ํ”ฝ ๋ณ€๋™์ด ํฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์™„๋ฒฝํ•ด!

3. ์‹œ๊ณ„์—ด ์ปฌ๋ ‰์…˜

MongoDB 5.0๋ถ€ํ„ฐ ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ๋ฅผ ์œ„ํ•œ ์ตœ์ ํ™”๋œ ์ปฌ๋ ‰์…˜ ํƒ€์ž…์ด ์ถ”๊ฐ€๋์–ด. IoT, ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๊ฐ€ ํ›จ์”ฌ ํšจ์œจ์ ์ด์•ผ!

4. ๋„ค์ดํ‹ฐ๋ธŒ ๋ถ„์„ ๊ธฐ๋Šฅ

MongoDB Atlas Data Lake๋ฅผ ํ†ตํ•ด S3์˜ ๋ฐ์ดํ„ฐ๋„ ์ง์ ‘ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด. ๋ณ„๋„์˜ ETL ์—†์ด ๋ถ„์„์ด ๊ฐ€๋Šฅํ•ด์กŒ์ง€!

๐Ÿ’Ž Cassandra์˜ ์ง„ํ™”
1. Cassandra 4.0์˜ ํ˜์‹ 

โ€ข Virtual Tables๋กœ ์‹œ์Šคํ…œ ์ •๋ณด ์กฐํšŒ ๊ฐœ์„ 
โ€ข Audit Logging ๊ธฐ๋ณธ ์ง€์›
โ€ข Zero Copy Streaming์œผ๋กœ ๋…ธ๋“œ ์ถ”๊ฐ€ ์†๋„ ํ–ฅ์ƒ
โ€ข Full Query Logging์œผ๋กœ ๋””๋ฒ„๊น… ๊ฐ•ํ™”

2. Kubernetes ๋„ค์ดํ‹ฐ๋ธŒ

K8ssandra ํ”„๋กœ์ ํŠธ๋ฅผ ํ†ตํ•ด Kubernetes์—์„œ Cassandra๋ฅผ ์‰ฝ๊ฒŒ ์šด์˜ํ•  ์ˆ˜ ์žˆ์–ด. ์ปจํ…Œ์ด๋„ˆ ํ™˜๊ฒฝ์— ์ตœ์ ํ™”!

3. DataStax Astra

์™„์ „ ๊ด€๋ฆฌํ˜• Cassandra ์„œ๋น„์Šค๋กœ, ์šด์˜ ๋ถ€๋‹ด ์—†์ด Cassandra์˜ ๊ฐ•๋ ฅํ•จ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด!

4. ๋จธ์‹ ๋Ÿฌ๋‹ ํ†ตํ•ฉ

Cassandra์— ์ €์žฅ๋œ ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ Spark์™€ ์—ฐ๋™ํ•ด์„œ ์‹ค์‹œ๊ฐ„ ML ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•์ด ๊ฐ€๋Šฅํ•ด!

๐Ÿ”ฎ ๊ณตํ†ต ํŠธ๋ Œ๋“œ
1. ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ํŠธ๋žœ์žญ์…˜/๋ถ„์„ ์ฒ˜๋ฆฌ (HTAP) ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ์™€ ๋ถ„์„์„ ํ•˜๋‚˜์˜ ์‹œ์Šคํ…œ์—์„œ! ์‹ค์‹œ๊ฐ„ ๋ถ„์„์ด ์ ์  ์ค‘์š”ํ•ด์ง€๊ณ  ์žˆ์–ด.

2. AI/ML ํ†ตํ•ฉ

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž์ฒด์— AI ๊ธฐ๋Šฅ์ด ํ†ตํ•ฉ๋˜๊ณ  ์žˆ์–ด. ์ž๋™ ์ธ๋ฑ์‹ฑ, ์ฟผ๋ฆฌ ์ตœ์ ํ™”, ์ด์ƒ ํƒ์ง€ ๋“ฑ!

3. ์—ฃ์ง€ ์ปดํ“จํŒ… ์ง€์›

IoT ๊ธฐ๊ธฐ์—์„œ ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ , ํ•„์š”ํ•œ ๊ฒƒ๋งŒ ์ค‘์•™์œผ๋กœ ์ „์†ก. ์ง€์—ฐ ์‹œ๊ฐ„ ์ตœ์†Œํ™”!

4. ํ”„๋ผ์ด๋ฒ„์‹œ ๊ฐ•ํ™”

GDPR, CCPA ๋“ฑ ๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ ๊ทœ์ •์— ๋Œ€์‘ํ•˜๋Š” ๊ธฐ๋Šฅ๋“ค์ด ๊ฐ•ํ™”๋˜๊ณ  ์žˆ์–ด. ๋ฐ์ดํ„ฐ ์•”ํ˜ธํ™”, ์ ‘๊ทผ ์ œ์–ด, ๊ฐ์‚ฌ ๋กœ๊ทธ ๋“ฑ!
## ๐ŸŽฌ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ ์™€! ์—ฌ๊ธฐ๊นŒ์ง€ ์ •๋ง ๊ธด ์—ฌ์ •์ด์—ˆ์–ด. MongoDB์™€ Cassandra์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๊ฒŒ ์•Œ์•„๋ดค์ง€? ๐Ÿ˜Š

ํ•ต์‹ฌ์„ ์ •๋ฆฌํ•˜์ž๋ฉด:

๐Ÿƒ MongoDB๋Š”: โ€ข ์œ ์—ฐํ•œ ์Šคํ‚ค๋งˆ๋กœ ๋น ๋ฅธ ๊ฐœ๋ฐœ
โ€ข ํ’๋ถ€ํ•œ ์ฟผ๋ฆฌ ๊ธฐ๋Šฅ
โ€ข ๋ฌธ์„œ ์ง€ํ–ฅ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ
โ€ข ์ค‘์†Œ๊ทœ๋ชจ๋ถ€ํ„ฐ ๋Œ€๊ทœ๋ชจ๊นŒ์ง€ ํ™•์žฅ ๊ฐ€๋Šฅ

๐ŸŒŸ Cassandra๋Š”:
โ€ข ์ดˆ๋Œ€๊ทœ๋ชจ ์“ฐ๊ธฐ ์„ฑ๋Šฅ
โ€ข ์„ ํ˜•์  ํ™•์žฅ์„ฑ
โ€ข ๋งˆ์Šคํ„ฐ๋ฆฌ์Šค ์•„ํ‚คํ…์ฒ˜๋กœ ๊ณ ๊ฐ€์šฉ์„ฑ
โ€ข ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ์— ์ตœ์ ํ™”
์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์„ ํƒํ• ์ง€๋Š” ํ”„๋กœ์ ํŠธ์˜ ์š”๊ตฌ์‚ฌํ•ญ์— ๋‹ฌ๋ ค์žˆ์–ด! ๋ณต์žกํ•œ ์ฟผ๋ฆฌ์™€ ์œ ์—ฐ์„ฑ์ด ํ•„์š”ํ•˜๋ฉด MongoDB, ๋Œ€๊ทœ๋ชจ ์“ฐ๊ธฐ์™€ ๊ณ ๊ฐ€์šฉ์„ฑ์ด ์ค‘์š”ํ•˜๋ฉด Cassandra๋ฅผ ์„ ํƒํ•˜๋ฉด ๋ผ. ๋•Œ๋กœ๋Š” ๋‘ ๊ฐ€์ง€๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ ‘๊ทผ๋„ ์ข‹์€ ์„ ํƒ์ด์•ผ! ๐ŸŽฏ

NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๊ณ„์† ์ง„ํ™”ํ•˜๊ณ  ์žˆ์–ด. ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ๋“ค์ด ์ถ”๊ฐ€๋˜๊ณ , ์„ฑ๋Šฅ์ด ๊ฐœ์„ ๋˜๊ณ , ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์›Œ์ง€๊ณ  ์žˆ์ง€. ์ง€์†์ ์œผ๋กœ ํ•™์Šตํ•˜๊ณ  ์‹คํ—˜ํ•˜๋ฉด์„œ ์ตœ์ ์˜ ์†”๋ฃจ์…˜์„ ์ฐพ์•„๊ฐ€๋Š” ๊ฒŒ ์ค‘์š”ํ•ด!

โš ๏ธ ๋งˆ์ง€๋ง‰ ์กฐ์–ธ: โ€ข ํ”„๋กœ๋•์…˜์— ์ ์šฉํ•˜๊ธฐ ์ „์— ๋ฐ˜๋“œ์‹œ ์ถฉ๋ถ„ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ!
โ€ข ๋ฐฑ์—…๊ณผ ๋ณต๊ตฌ ์ „๋žต์„ ๋จผ์ € ์ˆ˜๋ฆฝํ•˜๊ณ  ์‹œ์ž‘ํ•ด!
โ€ข ๋ชจ๋‹ˆํ„ฐ๋ง๊ณผ ์•Œ๋ฆผ ์‹œ์Šคํ…œ์„ ๊ผญ ๊ตฌ์ถ•ํ•ด!
โ€ข ๋ฌธ์„œํ™”๋ฅผ ๊ฒŒ์„๋ฆฌํ•˜์ง€ ๋ง ๊ฒƒ!
โ€ข ์ปค๋ฎค๋‹ˆํ‹ฐ๋ฅผ ์ ๊ทน ํ™œ์šฉํ•ด!
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ตฌ์ถ•์ด๋‚˜ ์ตœ์ ํ™”์— ์–ด๋ ค์›€์„ ๊ฒช๊ณ  ์žˆ๋‹ค๋ฉด, ์žฌ๋Šฅ๋„ท์—์„œ ๊ฒฝํ—˜ ๋งŽ์€ ์ „๋ฌธ๊ฐ€๋“ค์˜ ๋„์›€์„ ๋ฐ›์•„๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ. ํ˜ผ์ž ๊ณ ๋ฏผํ•˜์ง€ ๋ง๊ณ , ํ•จ๊ป˜ ํ•ด๊ฒฐํ•ด๋‚˜๊ฐ€์ž! ๐Ÿ’ช

์ด ๊ธ€์ด NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ดํ•ดํ•˜๊ณ  ํ™œ์šฉํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜์—ˆ๊ธฐ๋ฅผ ๋ฐ”๋ผ! ๊ถ๊ธˆํ•œ ์ ์ด ์žˆ๋‹ค๋ฉด ์–ธ์ œ๋“ ์ง€ ์ปค๋ฎค๋‹ˆํ‹ฐ์— ์งˆ๋ฌธํ•˜๊ณ , ๊ณ„์† ํ•™์Šตํ•˜๋ฉด์„œ ์„ฑ์žฅํ•ด๋‚˜๊ฐ€์ž. ํ™”์ดํŒ…! ๐Ÿš€โœจ

Happy Coding! ๐ŸŽ‰

๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์˜ ์„ธ๊ณ„๋กœ ์—ฌ๋Ÿฌ๋ถ„์„ ์ดˆ๋Œ€ํ•ฉ๋‹ˆ๋‹ค!

๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.