HOWTO · MongoDB
Python을 사용하여 MongoDB 데이터베이스에 로컬로 연결
이 Python MongoDB 자습서에서는 PyMongo의 기본 사항, Python을 사용하여 MongoDB 데이터베이스를 로컬로 연결하는 방법 및 몇 가지 간단한 데이터베이스 작업을 수행하는 방법을 배웁니다.
이 페이지의 내용
PyMongo를 사용하면 MongoDB 배포에 연결하고 데이터베이스와 컬렉션을 선택한 다음 BSON 문서를 삽입하거나 조회할 수 있습니다. 아래 예제는 MongoDB URI와 작은 쇼핑 목록 컬렉션을 사용합니다. URI의 자리표시자를 배포 환경의 연결 정보로 바꾸고, 인증 정보는 소스 제어에 포함하지 마세요. (insert_many(); insert_one())
Python과 PyMongo 설치
먼저 Python을 설치한 뒤 python -m pip install pymongo 명령으로 PyMongo를 설치합니다. 예제는 mongodb+srv://로 시작하는 DNS 시드 목록 URI를 사용하므로, DNS 지원도 python -m pip install "pymongo[srv]"로 설치하세요. 대신 dnspython을 별도로 설치해도 됩니다. 배포 환경에서 표준 mongodb:// URI를 제공한다면 해당 URI를 사용하고 네트워크 및 인증 설정을 따르세요.
프로그램을 pymongo_example.py로 저장하고 python pymongo_example.py를 실행하면 로컬 시연을 볼 수 있습니다. 데이터베이스 작업을 실행하려면 먼저 MongoDB 배포 환경의 연결 문자열을 MONGODB_URI에 설정한 다음 --database를 전달하세요. macOS 또는 Linux에서는 export MONGODB_URI='mongodb+srv://<username>:<password>@<cluster-name>/'를 사용하고, PowerShell에서는 $env:MONGODB_URI = 'mongodb+srv://<username>:<password>@<cluster-name>/'를 사용합니다. 자리표시자를 실제 값으로 바꾸고, URI 형식에 따라 필요한 경우 인증 정보의 특수 문자를 URL 인코딩하세요. 실제 인증 정보를 소스 제어나 공유 셸 기록에 남기지 마세요. 그런 다음 python pymongo_example.py --database를 실행합니다. 저장 경로와 실행 명령에 같은 파일 이름을 사용합니다.
PyMongo로 MongoDB에 연결
MongoDB 배포 환경에서 제공한 URI로 MongoClient를 만듭니다. 시드 목록 URI에는 클러스터 호스트가 포함되며 인증 옵션이 들어갈 수도 있습니다. <username>, <password>, <cluster-name>은 그대로 복사하지 말고 실제 값으로 바꾸세요. URI에 인증 정보가 들어 있을 수 있으므로 화면에 출력하지 마세요. 아래 데이터베이스 작업 분기는 --database를 지정했을 때만 선택되며 MONGODB_URI에서 URI를 읽습니다. 이 옵션이 없으면 프로그램은 별도의 오프라인 시연을 실행하고 MongoDB에 접속하지 않습니다.
애플리케이션에서는 MONGODB_URI 같은 환경 변수에서 URI를 읽어 MongoClient에 전달하세요. 스크립트에서는 모듈 수준의 if __name__ == "__main__": 가드 안에 작업을 넣어 파일을 가져오기만 할 때 데이터베이스 작업이 시작되지 않게 합니다. MongoClient는 지연 연결 방식이므로 첫 데이터베이스 작업 전에도 클라이언트를 만들 수 있습니다. 네트워크, DNS, 인증 또는 서버 선택 문제는 대개 첫 작업을 수행할 때 드러납니다. 작업이 끝나면 클라이언트를 닫고, 짧게 실행하는 스크립트라면 컨텍스트 관리자를 사용하세요.
데이터베이스와 컬렉션 만들기
client["user_shopping_list"]로 데이터베이스를 선택하고 database["items"]로 컬렉션을 선택합니다. 이 표현식은 핸들을 선택할 뿐, 데이터베이스나 컬렉션 데이터를 영구적으로 만들지는 않습니다. MongoDB는 처음 삽입 작업으로 데이터가 기록될 때 이를 생성합니다. 삽입과 조회 단계에서 일관된 이름을 사용하세요.
문서 삽입
Python 딕셔너리는 MongoDB 문서로 자연스럽게 변환됩니다. 데이터베이스 예제에서는 두 문서에 collection.insert_many(documents)를, 세 번째 문서에 collection.insert_one(document)을 사용합니다. 세 번째 문서에는 시간대 정보가 있는 Python datetime.datetime 값이 포함되어 있으며, PyMongo는 이를 BSON 날짜로 인코딩합니다. 반환된 결과 객체에서 삽입된 식별자를 얻어 방금 쓴 문서를 조회할 수 있습니다. MongoDB가 _id를 생성하게 하려면 이 필드를 생략하세요. 이 예제는 삽입한 레코드만 조회할 수 있도록 고유한 ID를 지정합니다.
삽입 작업을 하려면 MongoDB 배포 환경에 연결할 수 있어야 하고 쓰기 권한도 있어야 합니다. 중복 레코드를 허용하거나 예제에서 안정적인 식별자를 사용하고 중복 키 오류를 처리하지 않는 한, 공유 데이터베이스에서 샘플 삽입을 반복 실행하지 마세요.
문서 조회 및 누락 필드 처리
collection.find({})를 사용하면 모든 문서를 순회할 수 있습니다. 일치하는 문서만 가져오려면 {"category": "food"} 같은 필터를 전달하세요. 각 결과는 딕셔너리와 비슷한 형태입니다. item["category"]처럼 직접 조회하면 문서에 해당 키가 없을 때 KeyError가 발생합니다. 대체값이 적절한 경우에는 item.get("category", "(not set)")을 사용하세요. MongoDB의 find()는 커서를 반환하므로, 하나의 문서처럼 다루지 말고 순회해야 합니다.
이 로컬 시연을 실행하면 필드 구성이 서로 다른 문서를 출력에서 어떻게 처리하는지 확인할 수 있습니다. 이 시연은 오프라인으로 동작합니다. 위에서 설명한 대로 --database와 MONGODB_URI를 사용하면 데이터베이스 작업을 별도로 실행할 수 있습니다.
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.
import os
import sys
import uuid
from datetime import datetime, timezone
def show_documents(documents):
for item in documents:
print(item["item_name"], item.get("category", "(not set)"))
def run_database_workflow():
from pymongo import MongoClient
uri = os.environ.get("MONGODB_URI")
if not uri:
print("Set MONGODB_URI before running with --database.")
return
with MongoClient(uri) as client:
collection = client["user_shopping_list"]["items"]
many = [
{"_id": str(uuid.uuid4()), "item_name": "Bread", "category": "food"},
{"_id": str(uuid.uuid4()), "item_name": "Blender"},
]
many_result = collection.insert_many(many)
single = {
"_id": str(uuid.uuid4()),
"item_name": "Coffee",
"category": "food",
"added_at": datetime.now(timezone.utc),
}
single_result = collection.insert_one(single)
inserted_ids = many_result.inserted_ids + [single_result.inserted_id]
found = collection.find({"_id": {"$in": inserted_ids}})
show_documents(found)
def main():
if "--database" in sys.argv:
run_database_workflow()
else:
# This local sample needs no MongoDB server or connection URI.
show_documents([
{"item_name": "Bread", "category": "food"},
{"item_name": "Blender"},
])
if __name__ == "__main__":
main()
Bread food
Blender (not set)
로컬 예제의 출력은 다음과 같습니다.
데이터베이스 작업에서는 find()가 반환한 커서를 순회할 때 같은 안전한 필드 접근 방식을 사용합니다. 조회 결과가 없으면 커서에서 반환되는 행도 없습니다. 연결 실패라고 판단하기 전에 필터와 컬렉션 이름을 확인하세요. 이 모듈을 가져오면 함수 정의만 로드되며 main()을 호출하거나 데이터베이스 작업을 수행하지 않습니다.