FastAPI에 Mongo DB 연동하기

Garam·2024년 9월 16일
post-thumbnail

https://github.com/mongo-express/mongo-express
https://beanie-odm.dev/
https://motor.readthedocs.io/en/stable/tutorial-asyncio.html
https://blog.yevgnenll.me/posts/mongodb-and-express


MongoDB, Mongo Express (GUI) 설치 - Docker

docker-compose.yml

services:
  mongodb:
    image: mongo
    container_name: mongodb
    restart: always
    ports:
      - ${MONGO_DB_PORT}:${MONGO_DB_PORT}
    volumes:
      - ~/mongodb:/data/db
    environment:
      - MONGO_INITDB_ROOT_USERNAME=${MONGO_DB_USERNAME}
      - MONGO_INITDB_ROOT_PASSWORD=${MONGO_DB_PASSWORD}
      - MONGO_INITDB_DATABASE=${MONGO_DB_DATABASE}

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - ${MONGO_EXPRESS_PORT}:${MONGO_EXPRESS_PORT}
    environment:
      ME_CONFIG_BASICAUTH_ENABLED: true
      ME_CONFIG_BASICAUTH_USERNAME: ${MONGO_EXPRESS_USERNAME}
      ME_CONFIG_BASICAUTH_PASSWORD: ${MONGO_EXPRESS_PASSWORD}
      ME_CONFIG_MONGODB_URL: ${MONGO_EXPRESS_MONGODB_URL}
  • ME_CONFIG_BASICAUTH_ENABLED: true로 설정해야 Basic Authentication 사용 가능
  • 최초 ID, Password는 admin, pass

.env

# MONGO DB
MONGO_DB_PORT=27017
MONGO_DB_USERNAME=root
MONGO_DB_PASSWORD=1234
MONGO_DB_DATABASE=DB이름

# MONGO EXPRESS
MONGO_EXPRESS_PORT=8081
MONGO_EXPRESS_USERNAME=admin
MONGO_EXPRESS_PASSWORD=1234
MONGO_EXPRESS_MONGODB_URL=mongodb://root:1234@mongodb:27017
  • localhost:8081로 접속 시 admin, 1234로 로그인 가능



Beanie로 MongoDB 사용하기

Beanie

  • Python에서 MongoDB를 사용하기 위한 비동기 ODM(Object-Document Mapper) 라이브러리
  • asyncio를 사용하여 비동기 방식으로 MongoDB와 상호작용할 수 있어서 FastAPI 프로젝트에 사용하기 적합
  • MongoDB의 문서를 Python 객체로 매핑하여 편리하게 데이터베이스 작업을 수행함
  • Pydantic과 통합되어 데이터 유효성 검사와 스키마 정의를 쉽게 할 수 있음

Motor

  • Python에서 비동기적으로 MongoDB와 상호작용할 수 있게 해주는 비동기 MongoDB 드라이버
  • PyMongo 위에 비동기 기능을 추가한 라이브러리로, asyncio를 활용하여 비동기 I/O 작업을 수행
  • beanie는 비동기적으로 MongoDB와 상호작용할 수 있는 ODM이므로, 비동기 드라이버인 motor와 함께 사용해야 함

Installation

$ pip install beanie
  • 해당 명령 실행 시 motor도 함께 설치됨

Initialization

from typing import Optional

import motor.motor_asyncio
from motor.motor_asyncio import AsyncIOMotorClient
from pydantic import BaseModel

from beanie import Document, Indexed, init_beanie

class Category(BaseModel):
    name: str
    description: str

# DB에 저장될 모델의 schema
class Product(Document):
    name: str                          # You can use normal types just like in pydantic
    description: Optional[str] = None
    price: Indexed(float)              # You can also specify that a field should correspond to an index
    category: Category                 # You can include pydantic models as well

# Call this from within your event loop to get beanie setup.
async def init():
    # Create Motor client
    client = AsyncIOMotorClient("mongodb://user:pass@localhost:27017")

    # Init beanie with the Product document class
    await init_beanie(database=client.db_name, document_models=[Product])
  • init 메소드의 실행 시점?
    • FastAPI 프로젝트가 시작될 때 한 번만 호출하는 것이 좋음
    • MongoDB와 같은 NoSQL 데이터베이스에서는 전통적인 트랜잭션 기반의 연결 관리 방식보다는, 애플리케이션이 실행되는 동안 지속적인 연결을 유지하는 것이 일반적
  • init 시에 document_models로 Document 모델을 특정하는 이유?
    • MongoDB의 유연한 스키마는 특정 필드나 데이터 구조를 강제하지 않고, 다양한 형태의 데이터를 저장할 수 있는 장점을 제공
    • 그러나 애플리케이션 레벨에서 데이터를 구조화하고 관리할 때, 이 유연함이 오히려 복잡성을 야기할 수 있음
    • 모델을 정의하면 데이터가 저장되기 전에 Pydantic을 통해 유효성을 검사하여 데이터의 안정성을 높일 수 있음
    • 모델을 지정하지 않으면 Beanie는 해당 모델을 인식하지 못하여 MongoDB 컬렉션과의 매핑이 이루어지지 않고, 해당 모델을 통해 CRUD 작업을 할 수 없음

0개의 댓글