KR_MongoDB - somaz94/python-study GitHub Wiki

Python MongoDB ๊ฐœ๋… ์ •๋ฆฌ


1๏ธโƒฃ MongoDB ๊ธฐ์ดˆ

MongoDB๋Š” ๋ฌธ์„œ ์ง€ํ–ฅ NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๋‹ค.

from pymongo import MongoClient

# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ
client = MongoClient('mongodb://localhost:27017/')
db = client['mydatabase']

# ์ปฌ๋ ‰์…˜ ์ ‘๊ทผ
users = db.users
posts = db.posts

# ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•œ ์—ฐ๊ฒฐ ๋ฌธ์ž์—ด ๊ด€๋ฆฌ
import os
from dotenv import load_dotenv

load_dotenv()  # .env ํŒŒ์ผ์—์„œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๋กœ๋“œ
connection_string = os.getenv('MONGODB_URI')
secure_client = MongoClient(connection_string)

โœ… ํŠน์ง•:

  • ๋ฌธ์„œ ์ง€ํ–ฅ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
  • NoSQL ๊ตฌ์กฐ
  • ์œ ์—ฐํ•œ ์Šคํ‚ค๋งˆ
  • JSON ํ˜•์‹์˜ BSON ๋ฌธ์„œ
  • ๋ถ„์‚ฐ ์•„ํ‚คํ…์ฒ˜ ์ง€์›
  • ์ˆ˜ํ‰์  ํ™•์žฅ์„ฑ


2๏ธโƒฃ ๊ธฐ๋ณธ CRUD ์ž‘์—…

MongoDB์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒ์„ฑ, ์กฐํšŒ, ์ˆ˜์ •, ์‚ญ์ œํ•˜๋Š” ๊ธฐ๋ณธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

# ๋ฌธ์„œ ์ƒ์„ฑ (Create)
def create_user(user_data):
    try:
        result = users.insert_one(user_data)
        return str(result.inserted_id)
    except Exception as e:
        print(f"Error: {e}")
        return None

# ๋ฌธ์„œ ์กฐํšŒ (Read)
def get_user(user_id):
    from bson.objectid import ObjectId
    return users.find_one({'_id': ObjectId(user_id)})

# ์—ฌ๋Ÿฌ ๋ฌธ์„œ ์กฐํšŒ
def get_users(criteria=None, limit=10, skip=0):
    if criteria is None:
        criteria = {}
    cursor = users.find(criteria).limit(limit).skip(skip)
    return list(cursor)
    
# ๋ฌธ์„œ ์ˆ˜์ • (Update)
def update_user(user_id, update_data):
    from bson.objectid import ObjectId
    result = users.update_one(
        {'_id': ObjectId(user_id)},
        {'$set': update_data}
    )
    return result.modified_count > 0

# ๋ฌธ์„œ ์‚ญ์ œ (Delete)
def delete_user(user_id):
    from bson.objectid import ObjectId
    result = users.delete_one({'_id': ObjectId(user_id)})
    return result.deleted_count > 0

# ์‚ฌ์šฉ ์˜ˆ์‹œ
new_user = {
    'name': 'ํ™๊ธธ๋™',
    'email': '[email protected]',
    'age': 30,
    'interests': ['๋…์„œ', '๋“ฑ์‚ฐ', 'ํ”„๋กœ๊ทธ๋ž˜๋ฐ']
}

user_id = create_user(new_user)
print(f"์ƒ์„ฑ๋œ ์‚ฌ์šฉ์ž ID: {user_id}")

# ์‚ฌ์šฉ์ž ์กฐํšŒ
user = get_user(user_id)
print(f"์กฐํšŒ๋œ ์‚ฌ์šฉ์ž: {user}")

# ์‚ฌ์šฉ์ž ์ •๋ณด ์ˆ˜์ •
update_user(user_id, {'age': 31, 'interests': ['๋…์„œ', '๋“ฑ์‚ฐ', 'ํ”„๋กœ๊ทธ๋ž˜๋ฐ', '์—ฌํ–‰']})

# ์กฐ๊ฑด๋ถ€ ์ฟผ๋ฆฌ
young_users = get_users({'age': {'$lt': 35}})

โœ… ํŠน์ง•:

  • CRUD ์—ฐ์‚ฐ (Create, Read, Update, Delete)
  • ๊ฐ์ฒด ID ๊ด€๋ฆฌ
  • ์ฟผ๋ฆฌ ์—ฐ์‚ฐ์ž ($lt, $gt, $in ๋“ฑ)
  • ํ•„๋“œ ์—ฐ์‚ฐ์ž ($set, $inc, $push ๋“ฑ)
  • ์ •๋ ฌ, ์ œํ•œ, ๊ฑด๋„ˆ๋›ฐ๊ธฐ ๊ธฐ๋Šฅ
  • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฐ ์—๋Ÿฌ ๊ด€๋ฆฌ


3๏ธโƒฃ ๊ณ ๊ธ‰ ์ฟผ๋ฆฌ ์ž‘์—…

๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์กฐํšŒ ๋ฐ ๋ณ€ํ™˜์„ ์œ„ํ•œ ๊ณ ๊ธ‰ ์ฟผ๋ฆฌ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

# ๋ณต์žกํ•œ ์ฟผ๋ฆฌ
def find_active_users_with_posts():
    return users.aggregate([
        {
            '$match': {
                'status': 'active'
            }
        },
        {
            '$lookup': {
                'from': 'posts',
                'localField': '_id',
                'foreignField': 'user_id',
                'as': 'user_posts'
            }
        },
        {
            '$project': {
                'name': 1,
                'email': 1,
                'post_count': {'$size': '$user_posts'}
            }
        }
    ])

# ์ธ๋ฑ์Šค ์ƒ์„ฑ
def create_indexes():
    users.create_index([('email', 1)], unique=True)
    posts.create_index([('title', 'text'), ('content', 'text')])

# ๊ทธ๋ฃนํ™” ์ฟผ๋ฆฌ
def group_users_by_age():
    return list(users.aggregate([
        {
            '$group': {
                '_id': {
                    'age_group': {
                        '$switch': {
                            'branches': [
                                {'case': {'$lt': ['$age', 20]}, 'then': '10๋Œ€'},
                                {'case': {'$lt': ['$age', 30]}, 'then': '20๋Œ€'},
                                {'case': {'$lt': ['$age', 40]}, 'then': '30๋Œ€'}
                            ],
                            'default': '40๋Œ€ ์ด์ƒ'
                        }
                    }
                },
                'count': {'$sum': 1},
                'avg_age': {'$avg': '$age'}
            }
        },
        {
            '$sort': {'count': -1}
        }
    ]))

# ํ…์ŠคํŠธ ๊ฒ€์ƒ‰
def search_posts(query):
    return list(posts.find(
        {'$text': {'$search': query}},
        {'score': {'$meta': 'textScore'}}
    ).sort([('score', {'$meta': 'textScore'})]))

# ์ง€๋ฆฌ๊ณต๊ฐ„ ์ฟผ๋ฆฌ
def find_nearby_places(longitude, latitude, max_distance_km):
    return list(db.places.find({
        'location': {
            '$near': {
                '$geometry': {
                    'type': 'Point',
                    'coordinates': [longitude, latitude]
                },
                '$maxDistance': max_distance_km * 1000
            }
        }
    }))

โœ… ํŠน์ง•:

  • ์ง‘๊ณ„ ํŒŒ์ดํ”„๋ผ์ธ (aggregation)
  • ์กฐ์ธ ์—ฐ์‚ฐ ($lookup)
  • ํ•„๋“œ ํˆฌ์˜ ($project)
  • ๊ทธ๋ฃนํ™” ๋ฐ ์ง‘๊ณ„ ํ•จ์ˆ˜
  • ํ…์ŠคํŠธ ๊ฒ€์ƒ‰ ๋ฐ ์ธ๋ฑ์‹ฑ
  • ์ง€๋ฆฌ๊ณต๊ฐ„ ์ฟผ๋ฆฌ
  • ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ๋ฐ ๊ณ„์‚ฐ


4๏ธโƒฃ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง

MongoDB์— ์ €์žฅํ•  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ์ฒด ๋ชจ๋ธ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

from datetime import datetime
from bson.objectid import ObjectId

class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email
        self.created_at = datetime.utcnow()
    
    def to_dict(self):
        return {
            'name': self.name,
            'email': self.email,
            'created_at': self.created_at
        }
    
    @classmethod
    def from_dict(cls, data):
        user = cls(data['name'], data['email'])
        user.created_at = data.get('created_at', datetime.utcnow())
        return user

# ์ฐธ์กฐ ๊ด€๊ณ„ ๋ชจ๋ธ๋ง
class Post:
    def __init__(self, title, content, author_id):
        self.title = title
        self.content = content
        self.author_id = author_id  # User์˜ _id๋ฅผ ์ฐธ์กฐ
        self.created_at = datetime.utcnow()
        self.updated_at = self.created_at
        self.tags = []
    
    def to_dict(self):
        return {
            'title': self.title,
            'content': self.content,
            'author_id': self.author_id,
            'created_at': self.created_at,
            'updated_at': self.updated_at,
            'tags': self.tags
        }
    
    def add_tag(self, tag):
        if tag not in self.tags:
            self.tags.append(tag)
    
    @classmethod
    def from_dict(cls, data):
        post = cls(
            data['title'],
            data['content'],
            data['author_id']
        )
        post.created_at = data.get('created_at', datetime.utcnow())
        post.updated_at = data.get('updated_at', datetime.utcnow())
        post.tags = data.get('tags', [])
        return post

# ๋‚ด์žฅ ๋ฌธ์„œ ๋ชจ๋ธ๋ง
class Product:
    def __init__(self, name, price):
        self.name = name
        self.price = price
        self.created_at = datetime.utcnow()
        self.reviews = []  # ๋‚ด์žฅ ๋ฌธ์„œ
    
    def to_dict(self):
        return {
            'name': self.name,
            'price': self.price,
            'created_at': self.created_at,
            'reviews': self.reviews
        }
    
    def add_review(self, user_id, rating, comment):
        review = {
            'user_id': user_id,
            'rating': rating,
            'comment': comment,
            'created_at': datetime.utcnow()
        }
        self.reviews.append(review)

โœ… ํŠน์ง•:

  • ๊ฐ์ฒด-๋ฌธ์„œ ๋งคํ•‘
  • ์ฐธ์กฐ ๊ด€๊ณ„ vs ๋‚ด์žฅ ๋ฌธ์„œ
  • ์ง๋ ฌํ™” ๋ฐ ์—ญ์ง๋ ฌํ™”
  • ์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ
  • ์ปฌ๋ ‰์…˜ ๊ฐ„ ๊ด€๊ณ„ ์„ค๊ณ„
  • ์Šคํ‚ค๋งˆ ์œ ์—ฐ์„ฑ ํ™œ์šฉ
  • ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ ์ฒ˜๋ฆฌ


5๏ธโƒฃ ๋ฒŒํฌ ์ž‘์—…

๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋Šฅ์ด๋‹ค.

def bulk_insert(documents):
    try:
        result = users.insert_many(documents)
        return len(result.inserted_ids)
    except Exception as e:
        print(f"Bulk insert failed: {e}")
        return 0

def bulk_update(filter_criteria, update_data):
    try:
        result = users.update_many(
            filter_criteria,
            {'$set': update_data}
        )
        return result.modified_count
    except Exception as e:
        print(f"Bulk update failed: {e}")
        return 0

# ๋ฒŒํฌ ์ž‘์—… ์ „์šฉ API ์‚ฌ์šฉ
def perform_bulk_operations():
    from pymongo import UpdateOne, InsertOne, DeleteOne
    
    bulk_operations = [
        InsertOne({'name': '๊น€์ฒ ์ˆ˜', 'age': 25}),
        InsertOne({'name': '์ด์˜ํฌ', 'age': 28}),
        UpdateOne({'name': 'ํ™๊ธธ๋™'}, {'$set': {'age': 40}}),
        DeleteOne({'name': '๋ฐ•์ง€์„ฑ'})
    ]
    
    try:
        result = users.bulk_write(bulk_operations, ordered=False)
        print(f"์‚ฝ์ž…: {result.inserted_count}, ์ˆ˜์ •: {result.modified_count}, ์‚ญ์ œ: {result.deleted_count}")
        return True
    except Exception as e:
        print(f"Bulk operation failed: {e}")
        return False

# ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ
def process_large_dataset(file_path, batch_size=1000):
    import csv
    
    total_inserted = 0
    batch = []
    
    with open(file_path, 'r', encoding='utf-8') as csvfile:
        reader = csv.DictReader(csvfile)
        
        for i, row in enumerate(reader):
            # ํ•„๋“œ ๋ณ€ํ™˜ ๋ฐ ์ •์ œ
            if 'age' in row:
                row['age'] = int(row['age'])
            
            batch.append(row)
            
            # ๋ฐฐ์น˜ ํฌ๊ธฐ์— ๋„๋‹ฌํ•˜๋ฉด ์‚ฝ์ž…
            if len(batch) >= batch_size:
                inserted = bulk_insert(batch)
                total_inserted += inserted
                print(f"Inserted {inserted} documents. Total: {total_inserted}")
                batch = []
        
        # ๋‚จ์€ ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ
        if batch:
            inserted = bulk_insert(batch)
            total_inserted += inserted
            print(f"Inserted {inserted} documents. Total: {total_inserted}")
    
    return total_inserted

โœ… ํŠน์ง•:

  • ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์‚ฝ์ž…
  • ์ผ๊ด„ ์—…๋ฐ์ดํŠธ
  • ๋ฒŒํฌ ์ž‘์—… API
  • ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ
  • ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ์…‹ ๊ด€๋ฆฌ
  • ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ
  • ์„ฑ๋Šฅ ์ตœ์ ํ™”


6๏ธโƒฃ ํŠธ๋žœ์žญ์…˜๊ณผ ์—๋Ÿฌ ์ฒ˜๋ฆฌ

์›์ž์  ์—ฐ์‚ฐ๊ณผ ์—๋Ÿฌ ๋ณต๊ตฌ๋ฅผ ์œ„ํ•œ ํŠธ๋žœ์žญ์…˜ ๊ธฐ๋Šฅ์ด๋‹ค.

def transfer_points(from_user_id, to_user_id, points):
    from bson.objectid import ObjectId
    from pymongo.errors import PyMongoError
    
    # ์„ธ์…˜ ์‹œ์ž‘
    with client.start_session() as session:
        try:
            # ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘
            with session.start_transaction():
                # ํฌ์ธํŠธ ์ฐจ๊ฐ
                from_result = users.update_one(
                    {'_id': ObjectId(from_user_id)},
                    {'$inc': {'points': -points}},
                    session=session
                )
                
                if from_result.modified_count == 0:
                    raise ValueError(f"User {from_user_id} not found or not enough points")
                
                # ํฌ์ธํŠธ ์ถ”๊ฐ€
                to_result = users.update_one(
                    {'_id': ObjectId(to_user_id)},
                    {'$inc': {'points': points}},
                    session=session
                )
                
                if to_result.modified_count == 0:
                    raise ValueError(f"User {to_user_id} not found")
                
                # ํŠธ๋žœ์žญ์…˜ ๋กœ๊ทธ ๊ธฐ๋ก
                db.transactions.insert_one({
                    'from_user': ObjectId(from_user_id),
                    'to_user': ObjectId(to_user_id),
                    'points': points,
                    'timestamp': datetime.utcnow()
                }, session=session)
                
                return True
                
        except (PyMongoError, ValueError) as e:
            print(f"Transaction failed: {e}")
            return False

# ์žฌ์‹œ๋„ ๋กœ์ง
def retry_operation(operation_func, max_retries=3, *args, **kwargs):
    from pymongo.errors import ConnectionFailure, OperationFailure
    
    retries = 0
    while retries < max_retries:
        try:
            return operation_func(*args, **kwargs)
        except (ConnectionFailure, OperationFailure) as e:
            retries += 1
            wait_time = 0.5 * (2 ** retries)  # ์ง€์ˆ˜ ๋ฐฑ์˜คํ”„
            print(f"Operation failed: {e}. Retrying in {wait_time}s ({retries}/{max_retries})")
            import time
            time.sleep(wait_time)
    
    # ๋ชจ๋“  ์žฌ์‹œ๋„ ์‹คํŒจ
    raise Exception(f"Operation failed after {max_retries} retries")

โœ… ํŠน์ง•:

  • ์„ธ์…˜ ๋ฐ ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ
  • ACID ํŠน์„ฑ ์ง€์›
  • ์›์ž์  ์ž‘์—… ์ฒ˜๋ฆฌ
  • ์—๋Ÿฌ ๋ณต๊ตฌ ๋ฐ ์žฌ์‹œ๋„
  • ๋ถ„์‚ฐ ํŠธ๋žœ์žญ์…˜
  • ๋กค๋ฐฑ ๋ฉ”์ปค๋‹ˆ์ฆ˜
  • ์ง€์ˆ˜ ๋ฐฑ์˜คํ”„ ์ „๋žต


7๏ธโƒฃ ์„ฑ๋Šฅ ์ตœ์ ํ™”

MongoDB ์ฟผ๋ฆฌ ๋ฐ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๋Š” ๊ธฐ๋ฒ•์ด๋‹ค.

# ์ฟผ๋ฆฌ ํ”„๋กœํŒŒ์ผ๋ง
def analyze_slow_queries():
    # ํ”„๋กœํŒŒ์ผ๋ง ๋ ˆ๋ฒจ ์„ค์ • (0=๊บผ์ง, 1=๋А๋ฆฐ ์ฟผ๋ฆฌ๋งŒ, 2=๋ชจ๋“  ์ฟผ๋ฆฌ)
    db.command({"profile": 1, "slowms": 100})
    
    # ๋А๋ฆฐ ์ฟผ๋ฆฌ ํ™•์ธ
    slow_queries = list(db.system.profile.find().sort("millis", -1).limit(10))
    for query in slow_queries:
        print(f"Slow query: {query['op']} - {query['millis']}ms")
        print(f"Query: {query['query']}")
        print(f"Namespace: {query['ns']}")
        print("-" * 50)
    
    return slow_queries

# ๋ฐ์ดํ„ฐ ๋ชจ๋ธ ์ตœ์ ํ™” (์˜ˆ: ์ธ๋ฑ์Šค ์ถ”์ฒœ)
def suggest_indexes():
    # ํ˜„์žฌ ์ธ๋ฑ์Šค ํ™•์ธ
    current_indexes = list(users.list_indexes())
    print(f"Current indexes: {len(current_indexes)}")
    
    # ์ธ๋ฑ์Šค ์ถ”์ฒœ ๋กœ์ง
    pipeline = [
        {"$indexStats": {}},
        {"$sort": {"accesses.ops": -1}}
    ]
    
    index_stats = list(users.aggregate(pipeline))
    
    # ์ถ”์ฒœ ์ธ๋ฑ์Šค ์ƒ์„ฑ
    recommendations = []
    for stat in index_stats:
        if stat["accesses"]["ops"] > 1000:
            # ์ธ๋ฑ์Šค ๊ณ„ํš ์„ค์ • ์˜ˆ์‹œ
            recommendations.append({
                "collection": stat["name"],
                "field": stat["key"].keys(),
                "ops": stat["accesses"]["ops"]
            })
    
    return recommendations

# ์ฟผ๋ฆฌ ์ตœ์ ํ™” - ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค ํ™œ์šฉ
def optimized_users_query(min_age, max_age):
    # 1. ์ธ๋ฑ์Šค ์ƒ์„ฑ
    users.create_index([("age", 1), ("name", 1)])
    
    # 2. ์ธ๋ฑ์Šค๋งŒ ์‚ฌ์šฉํ•˜๋Š” ์ฟผ๋ฆฌ (ํ•„๋“œ ํ”„๋กœ์ ์…˜์— ์ฃผ์˜)
    result = users.find(
        {"age": {"$gte": min_age, "$lte": max_age}},
        {"_id": 0, "name": 1, "age": 1}  # ์ธ๋ฑ์Šค์— ํฌํ•จ๋œ ํ•„๋“œ๋งŒ ์‚ฌ์šฉ
    ).hint([("age", 1), ("name", 1)])  # ๋ช…์‹œ์  ์ธ๋ฑ์Šค ์‚ฌ์šฉ
    
    return list(result)

# ์บ์‹ฑ ๋ ˆ์ด์–ด ๊ตฌํ˜„
import functools

def cached_query(ttl_seconds=300):
    """์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์บ์‹ฑํ•˜๋Š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ"""
    cache = {}
    
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # ์บ์‹œ ํ‚ค ์ƒ์„ฑ
            key = str(args) + str(kwargs)
            
            # ์บ์‹œ ํ™•์ธ
            now = datetime.utcnow()
            if key in cache and (now - cache[key]["timestamp"]).total_seconds() < ttl_seconds:
                print("Cache hit!")
                return cache[key]["result"]
            
            # ์บ์‹œ ๋ฏธ์Šค - ํ•จ์ˆ˜ ์‹คํ–‰ ๋ฐ ๊ฒฐ๊ณผ ์บ์‹ฑ
            result = func(*args, **kwargs)
            cache[key] = {"result": result, "timestamp": now}
            print("Cache miss - updated cache")
            
            return result
        return wrapper
    return decorator

@cached_query(ttl_seconds=60)
def get_popular_posts(limit=10):
    return list(posts.find().sort("views", -1).limit(limit))

โœ… ํŠน์ง•:

  • ์ฟผ๋ฆฌ ํ”„๋กœํŒŒ์ผ๋ง
  • ์ธ๋ฑ์Šค ์ตœ์ ํ™”
  • ์ฟผ๋ฆฌ ๊ณ„ํš ๋ถ„์„
  • ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค ํ™œ์šฉ
  • ์บ์‹ฑ ์ „๋žต
  • ์„ฑ๋Šฅ ๋ณ‘๋ชฉ ์‹๋ณ„
  • ๋ฐ์ดํ„ฐ ๋ชจ๋ธ ์ตœ์ ํ™”
  • ๋ฆฌ๋“œ/๋ผ์ดํŠธ ๋ถ€ํ•˜ ๊ด€๋ฆฌ


์ฃผ์š” ํŒ

โœ… ๋ชจ๋ฒ” ์‚ฌ๋ก€:

  • ์ ์ ˆํ•œ ์ธ๋ฑ์Šค ์„ค๊ณ„ ๋ฐ ๊ด€๋ฆฌ
    • ์ฟผ๋ฆฌ ํŒจํ„ด์„ ๋ถ„์„ํ•˜์—ฌ ์ธ๋ฑ์Šค ์„ค๊ณ„
    • ๋ณตํ•ฉ ์ธ๋ฑ์Šค์™€ ๋‹จ์ผ ์ธ๋ฑ์Šค์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„ ํ‰๊ฐ€
    • ๋ถˆํ•„์š”ํ•œ ์ธ๋ฑ์Šค ์ œ๊ฑฐ๋กœ ์“ฐ๊ธฐ ์„ฑ๋Šฅ ํ–ฅ์ƒ
  • ์ƒค๋”ฉ ์ „๋žต ์ˆ˜๋ฆฝ
    • ๋ฐ์ดํ„ฐ ๊ทœ๋ชจ๊ฐ€ ํด ๋•Œ ์ƒค๋“œ ํ‚ค ์‹ ์ค‘ํžˆ ์„ ํƒ
    • ๊ท ๋“ฑํ•œ ๋ฐ์ดํ„ฐ ๋ถ„ํฌ๋ฅผ ์œ„ํ•œ ์„ค๊ณ„
  • ๋ณต์ œ ์„ธํŠธ ๊ตฌ์„ฑ ๋ฐ ๊ด€๋ฆฌ
    • ๊ณ ๊ฐ€์šฉ์„ฑ์„ ์œ„ํ•œ ๋‹ค์ค‘ ๋…ธ๋“œ ์„ค์ •
    • ์ฝ๊ธฐ ์Šค์ผ€์ผ๋ง์„ ์œ„ํ•œ ๋ณด์กฐ ๋…ธ๋“œ ํ™œ์šฉ
  • ํŠธ๋žœ์žญ์…˜ ์ ์ ˆํžˆ ํ™œ์šฉ
    • ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ํŠธ๋žœ์žญ์…˜ ์‚ฌ์šฉ
    • ํŠธ๋žœ์žญ์…˜์˜ ๋ฒ”์œ„๋ฅผ ์ตœ์†Œํ™”
  • ๋ฐ์ดํ„ฐ ๋ชจ๋ธ๋ง ์ตœ์ ํ™”
    • ๋‚ด์žฅ ๋ฌธ์„œ vs ์ฐธ์กฐ ๊ด€๊ณ„ ์ ์ ˆํžˆ ์„ ํƒ
    • ์•ก์„ธ์Šค ํŒจํ„ด์— ๋”ฐ๋ฅธ ์Šคํ‚ค๋งˆ ์„ค๊ณ„
    • ๋ฐ์ดํ„ฐ ์ •๊ทœํ™”์™€ ๋น„์ •๊ทœํ™” ๊ท ํ˜• ์œ ์ง€
  • ์ฟผ๋ฆฌ ์„ฑ๋Šฅ ๋ชจ๋‹ˆํ„ฐ๋ง
    • ๋А๋ฆฐ ์ฟผ๋ฆฌ ํ”„๋กœํŒŒ์ผ๋ง ํ™œ์„ฑํ™”
    • ์ฟผ๋ฆฌ ๊ณ„ํš ๋ถ„์„์œผ๋กœ ์„ฑ๋Šฅ ๋ณ‘๋ชฉ ์‹๋ณ„
  • ๋ฐฑ์—… ์ „๋žต ๊ตฌํ˜„
    • ์ •๊ธฐ์ ์ธ ๋ฐฑ์—… ์Šค์ผ€์ค„ ์ˆ˜๋ฆฝ
    • ๋ณต๊ตฌ ์ ˆ์ฐจ ๋ฌธ์„œํ™” ๋ฐ ํ…Œ์ŠคํŠธ
  • ๋ณด์•ˆ ์„ค์ • ์ตœ์ ํ™”
    • ์ธ์ฆ ๋ฐ ๊ถŒํ•œ ๋ชจ๋ธ ๊ตฌํ˜„
    • ๋„คํŠธ์›Œํฌ ๋ณด์•ˆ ๊ฐ•ํ™”
    • ๋ฏผ๊ฐ ๋ฐ์ดํ„ฐ ์•”ํ˜ธํ™” ๊ณ ๋ ค
  • ๋„๊ตฌ ํ™œ์šฉ
    • MongoDB Compass๋ฅผ ํ†ตํ•œ ์‹œ๊ฐ์  ๊ด€๋ฆฌ
    • Aggregation Builder๋กœ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ ์ž‘์„ฑ
    • MongoDB Atlas ๋ชจ๋‹ˆํ„ฐ๋ง ๋„๊ตฌ ํ™œ์šฉ


โš ๏ธ **GitHub.com Fallback** โš ๏ธ