개요
FastAPI는 표준 Python 유형 힌트를 사용하여 API를 빌드하도록 설계된 최신 고성능 프로덕션용 비동기 Python 웹 프레임워크 입니다. 이 튜토리얼에서는 MongoDB 와 FastAPI를 통합하는 완전한 CRUD 애플리케이션 빌드 방법을 학습 수 있습니다.
논블로킹 아키텍처
FastAPI의 비동기 비차단 아키텍처를 사용하면 멀티스레딩에 의존하지 않고도 수천 개의 동시 요청을 처리하다 할 수 있습니다. Python의 asyncio
이벤트 루프 사용하여 코루틴을 통해 동시성을 관리 . 이를 통해 애플리케이션 쿼리가 반환되기를 기다리는 동안 요청 일시 중단할 수 있습니다. 이렇게 하면 메모리 사용량이 줄어들고 지연 시간 줄어들 수 있습니다.
내장 기능 및 통합
FastAPI에는 다음 구성 요소를 포함하여 몇 가지 내장 통합 및 기능이 있습니다.
자동 데이터 구문 분석, 유효성 검사 및 직렬화를 위한 Pydantic
자동 생성된 대화형 API 문서를 위한 OpenAPI 및 JSON schema
깔끔하고 테스트 가능한 코드를 위한 경량 Pythonic 종속성 주입 시스템
OAuth2 및 JSON web token 인증 및 권한 부여 부여 지원
이러한 기능은 상용구 코드를 최소화하여 개발을 간소화합니다. FastAPI의 기능에 대한 자세한 내용은 FastAPI 웹사이트 참조하세요.
튜토리얼
이 튜토리얼의 완성된 샘플 앱 MongoDB with FastAPI 샘플 프로젝트 GitHub 리포지토리 에서 찾을 수 있습니다.
전제 조건
이 튜토리얼을 시작하기 전에 다음 구성 요소가 설치 및 설정하다 되어 있는지 확인하십시오.
Python v3.9 - 3.11
MongoDB Atlas cluster. 클러스터 설정하다 방법에 학습 자세한 내용은 시작하기 가이드 참조하세요.
설정
종속성을 설치하고 MongoDB 에 연결한 다음 FastAPI 서버 시작합니다.
예시 코드 예시 복제
터미널에서 다음 명령을 실행하여 mongodb-pymongo-fastapi GitHub 리포지토리 에서 코드를 복제합니다.
git clone git@github.com:mongodb-developer/mongodb-pymongo-fastapi.git cd mongodb-pymongo-fastapi
필수 종속성 설치
팁
가상 환경 활성화
가상 환경에 Python 종속성을 설치하면 개별 프로젝트에 대한 라이브러리 버전을 설치할 수 있습니다.pip
명령을 실행 전에 virtualenv
가 활성화되어 있는지 확인합니다.
터미널에서 다음 명령을 실행하여 requirements.txt
파일 에 나열된 종속성을 설치합니다.
cd mongodb-pymongo-fastapi pip install -r requirements.txt
종속성을 다운로드 하고 설치하는 데 몇 분 정도 걸릴 수 있습니다.
연결 문자열 조회
MongoDB Atlas 연결 문자열 찾기 가이드 에 따라 연결 문자열 조회 합니다.
터미널에서 다음 코드를 실행하여 연결 문자열 저장 환경 변수를 만듭니다.
export MONGODB_URL="mongodb+srv://<username>:<password>@<url>/<db>?retryWrites=true&w=majority"
클러스터에 애플리케이션 연결
예시 애플리케이션 의 모든 코드는 mongodb-pymongo-fastapi GitHub 리포지토리 의 앱.py 파일 에 저장됩니다.
이 코드를 사용하여 다음 작업을 수행합니다.
MONGODB_URL
환경 변수와 함께AsyncMongoClient()
메서드를 사용하고college
라는 데이터베이스 지정하여 MongoDB Atlas cluster 에 연결합니다.college
데이터베이스 에 대한 포인터를 만듭니다.students
컬렉션 에 대한 포인터 만들기
client = AsyncMongoClient(os.environ["MONGODB_URL"],server_api=pymongo.server_api.ServerApi(version="1", strict=True,deprecation_errors=True)) db = client.get_database("college") student_collection = db.get_collection("students")
AsyncMongoClient()
호출에는 연결에서 Stable API 기능 활성화 하는 server_api
매개 변수가 포함되어 있습니다. 배포서버 버전이 5.0 이상인 MongoDB 서버를 사용하는지 확인합니다. 자세한 내용은 이 가이드의 Stable API 섹션을 참조하세요.
데이터베이스 모델 검토
이 애플리케이션 에는 StudentModel
, UpdateStudentModel
, StudentCollection
의 세 가지 모델이 있습니다. 이러한 모델은 app.py
파일 에 정의되어 있습니다.
애플리케이션 의 모든 모델은 BaseModel
기본 유형 유효성 검사, JSON 구문 분석 및 직렬화, 기본 오류 처리를 제공하는 Pydantic 를 기반으로 빌드 .
StudentModel 클래스
StudentModel
대부분의 엔드포인트에 대한 응답 모델로 사용되는 프라이머리 모델입니다.
MongoDB _id
을 문서의 기본값 식별자로 사용합니다. 그러나 Pydantic에서 밑줄로 시작하는 필드 이름은 비공개 속성으로 취급되며 직접 값을 할당할 수 없습니다. 이 문제를 해결하기 위해 Pydantic 모델에서 필드 이름을 id
으로 지정할 수 있지만 MongoDB 에 올바르게 매핑되도록 별칭을 _id
로 지정합니다.
id
필드 값을 문자열로 강제 변환하는 BeforeValidator
주석이 달린 사용자 지정 유형인 PyObjectId
유형입니다. 이렇게 하면 MongoDB의 ObjectId
이 모델에서 올바르게 허용되고 직렬화될 수 있습니다.
이 설정 다음 model_config
옵션이 필요합니다.
populate_by_name=True
: 필드 이름(id
) 또는 해당 별칭(_id
)을 사용하여 모델을 초기화할 수 있습니다.arbitrary_types_allowed=True
: 다음과 같은 사용자 지정 유형을 지원 합니다.PyObjectId
id
필드 도 기본값 이 None
인 선택 사항으로 정의되어 있으므로 id
을 지정하지 않고도 새 StudentModel
인스턴스 만들 수 있습니다. 문서 삽입되면 MongoDB 자동으로 _id
를 생성하고, 이 값은 API 응답으로 반환됩니다.
model_config
에는 FastAPI의 자동 생성 OpenAPI(Swagger) 문서에 사용되는 예시 데이터를 정의하는 json_schema_extra
설정도 포함되어 있습니다.
app.py
파일 의 다음 코드에서 StudentModel
정의를 볼 수 있습니다.
# Represents an ObjectId field in the database. # It will be represented as a `str` on the model so that it can be serialized to JSON. PyObjectId = Annotated[str, BeforeValidator(str)] class StudentModel(BaseModel): """ Container for a single student record. """ # The primary key for the StudentModel, stored as a `str` on the instance. # This will be aliased to ``_id`` when sent to MongoDB, # but provided as ``id`` in the API requests and responses. id: Optional[PyObjectId] = Field(alias="_id", default=None) name: str = Field(...) email: EmailStr = Field(...) course: str = Field(...) gpa: float = Field(..., le=4.0) model_config = ConfigDict( populate_by_name=True, arbitrary_types_allowed=True, json_schema_extra={ "example": { "name": "Jane Doe", "email": "jdoe@example.com", "course": "Experiments, Science, and Fashion in Nanophotonics", "gpa": 3.0, } }, )
UpdateStudentModel 클래스
UpdateStudentModel
에는 StudentModel
과의 주요 차이점이 있습니다.
수정할 수 없으므로
id
속성이 없습니다.모든 필드는 선택 사항이므로 업데이트 하려는 필드만 제공할 수 있습니다.
mongo_config
변수에는json_encoders={ObjectId: str}
가 포함됩니다.
FastAPI는 데이터를 JSON 문자열로 인코딩 및 디코딩하며, MongoDB의 BSON 데이터 유형 저장 수 있는 모든 데이터 유형을 지원 하지는 않습니다. BSON 기본값 UUID 속성인 _id
에 사용되는 ObjectId
을 포함하여 더 많은 비 JSON 네이티브 데이터 유형을 지원 합니다. 이 때문에 ObjectId
객체를 _id
필드 에 저장하기 전에 문자열로 변환해야 합니다. json_encoders
설정은 Pydantic에 이 작업을 수행하도록 지시합니다.
BSON JSON 과 비교하는 방법에 대한 자세한 내용은 JSON 및 BSON MongoDB 문서를 참조하세요.
app.py
파일 의 다음 코드에서 UpdateStudentModel
정의를 볼 수 있습니다.
class UpdateStudentModel(BaseModel): """ A set of optional updates to be made to a document in the database. """ name: Optional[str] = None email: Optional[EmailStr] = None course: Optional[str] = None gpa: Optional[float] = None model_config = ConfigDict( arbitrary_types_allowed=True, json_encoders={ObjectId: str}, json_schema_extra={ "example": { "name": "Jane Doe", "email": "jdoe@example.com", "course": "Experiments, Science, and Fashion in anophotonics", "gpa": 3.0, } }, )
StudentCollection 클래스
StudentCollection
클래스는 인스턴스 목록을 캡슐화하도록 정의되어 StudentModel
있습니다. 이 엔드포인트의 목적은 악의적인 사용자가 브라우저가 JSON 배열을 처리하다 방식을 악용하여 민감한 데이터에 액세스 시도하는 JSON 하이재킹으로부터 일부 보호 기능을 제공하는 것입니다. 자세한 내용은 Haacked 웹사이트 에서 JSON 하이재킹 문서를 참조하세요.
app.py
파일 의 다음 코드에서 StudentCollection
정의를 볼 수 있습니다.
class StudentCollection(BaseModel): """ A container holding a list of `StudentModel` instances """ students: List[StudentModel]
애플리케이션 라우트 검토
다음 표에서는 이 애플리케이션 에 정의된 애플리케이션 경로에 대해 설명합니다.
루트 | 작업 |
---|---|
| 새 학생 만들기 |
| 모든 학생 목록 보기 |
| 단일 학생 보기 |
| 학생 업데이트 |
| 학생 삭제 |
이러한 경로는 다음 섹션에 설명된 대로 app.py
파일 에 정의되어 있습니다.
학생 루트
create_student
경로는 POST
요청 에서 새 학생 데이터를 JSON 문자열로 수신합니다. JSON 요청 본문을 Python 사전으로 디코딩한 다음 MongoDB 클라이언트 에 전달합니다.
insert_one
메서드 응답에는 새로 생성된 학생의 _id
가 포함되며, 이 엔드포인트가 post
데코레이터 호출에서 response_model_by_alias=False
을(를) 지정하기 때문에 id
(으)로 제공됩니다. 새 학생을 삽입한 후 이 메서드는 inserted_id
를 사용하여 올바른 문서 찾고 이를 JSONResponse
에 반환합니다.
FastAPI는 기본값 으로 HTTP 200
상태 코드를 반환하지만, 이 경로는 학생이 생성되었음을 명시적으로 나타내기 위해 201
('생성됨')을 반환합니다.
app.py
파일 의 다음 코드에서 create_student
정의를 볼 수 있습니다.
async def create_student(student: StudentModel = Body(...)): """ Insert a new student record. A unique ``id`` will be created and provided in the response. """ new_student = student.model_dump(by_alias=True, exclude=["id"]) result = await student_collection.insert_one(new_student) new_student["_id"] = result.inserted_id return new_student
경로 읽기
애플리케이션 에는 모든 학생을 보는 경로와 id
(으)로 지정된 개별 학생을 보는 경로가 있습니다.
app.py
파일 의 다음 코드에서 list_students
정의를 볼 수 있습니다.
async def list_students(): """ List all the student data in the database. The response is unpaginated and limited to 1000 results. """ return StudentCollection(students=await student_collection.find().to_list(1000))
참고
결과 페이지 매김
이 예시 메서드를 to_list()
사용합니다. 그러나 실제 애플리케이션 에서는 의 건너뛰기 및 제한 매개변수를 사용하여 find
결과를 페이지 매김하는 것이 좋습니다.
학생 세부 정보 경로에는 FastAPI가 show_student
함수에 인수로 전달하는 id
경로 매개 변수가 있습니다. id
를 사용하여 데이터베이스 에서 해당 학생을 찾으려고 시도합니다.
지정된 id
가 있는 문서 존재하지 않으면 HTTPException
상태가 404
인 문서가 발생합니다.
app.py
파일 의 다음 코드에서 show_students
정의를 볼 수 있습니다.
async def show_student(id: str): """ Get the record for a specific student, looked up by ``id``. """ if ( student := await student_collection.find_one({"_id": ObjectId(id)}) ) is not None: return student raise HTTPException(status_code=404, detail="Student {id} not found")
경로 업데이트
update_student
경로는 create_student
및 show_student
경로의 조합과 유사하게 작동합니다. 업데이트 할 학생의 id
와 JSON 본문의 새 데이터를 수신합니다.
이 경로는 수신된 데이터의 모든 매개변수를 반복하고 제공된 매개변수만 수정합니다.find_one_and_update() to $ 설정하다 메서드를 사용합니다.
업데이트 할 필드가 없는 경우 원본 StudentModel
문서 반환합니다. 업데이트 하거나 반환할 일치하는 문서 찾을 수 없으면 404
오류가 발생합니다.
app.py
파일 의 다음 코드에서 update_student
정의를 볼 수 있습니다.
async def update_student(id: str, student: UpdateStudentModel = Body(...)): """ Update individual fields of an existing student record. Only the provided fields will be updated. Any missing or `null` fields will be ignored. """ student = { k: v for k, v in student.model_dump(by_alias=True).items() if v is not None } if len(student) >= 1: update_result = await student_collection.find_one_and_update( {"_id": ObjectId(id)}, {"$set": student}, return_document=ReturnDocument.AFTER, ) if update_result is not None: return update_result else: raise HTTPException(status_code=404, detail=f"Student {id} not found") # The update is empty, so return the matching document: if (existing_student := await student_collection.find_one({"_id": ObjectId(id)})) is not None: return existing_student raise HTTPException(status_code=404, detail=f"Student {id} not found")
경로 삭제
delete_student
는 단일 문서 에서 작동하므로 URL 에 id
를 제공해야 합니다. 일치하는 문서 찾아서 성공적으로 삭제하면 HTTP 상태 204
('콘텐츠 없음')을 반환하고 문서 반환하지 않습니다. 지정된 id
를 가진 학생을 찾을 수 없는 경우 404
오류를 반환합니다.
app.py
파일 의 다음 코드에서 delete_student
정의를 볼 수 있습니다.
async def delete_student(id: str): """ Remove a single student record from the database. """ delete_result = await student_collection.delete_one({"_id": ObjectId(id)}) if delete_result.deleted_count == 1: return Response(status_code=status.HTTP_204_NO_CONTENT) raise HTTPException(status_code=404, detail=f"Student {id} not found")
API 테스트
이제 애플리케이션 의 작동 방식을 이해했으므로 엔드포인트 사용을 시작할 수 있습니다. 엔드포인트에 요청을 보내고 결과를 확인하려면 다음 단계를 따르세요.
요청 보내기
http://:127.0.0.1 8000/docs 로 이동합니다. 다음 이미지는 FastAPI 서버 에서 생성된 인터페이스를 보여줍니다.

요청 보내려는 엔드포인트를 클릭하고 필요한 매개변수를 입력한 다음 Execute을 클릭합니다. Show Student 엔드포인트에서 StudentModel.model_config
변수에 정의된 샘플 데이터를 볼 수 있습니다.
팁
curl을 사용하여 API 테스트
명령줄 사용을 선호하는 경우 다음과 같은 curl
명령을 사용하여 요청 보낼 수 있습니다.
curl -X POST "http://127.0.0.1:8000/students/" \ -H "Content-Type: application/json" \ -d '{"name": "Jane Doe", "email": "jdoe@example.com", "course": "Physics", "gpa": 3.8}'
다음 단계
이제 FastAPI가 MongoDB 및 PyMongo 비동기 운전자 와 통합되는 방식에 대한 기본 사항을 이해했으므로 더 많은 기능을 추가할 수 있습니다. 다음 목록에는 이 애플리케이션 에 추가할 수 있는 방법에 대한 몇 가지 제안 사항이 포함되어 있습니다.
모범 사례
다음 섹션에서는 FastAPI를 MongoDB 및 PyMongo 비동기 운전자 와 통합하기 위한 몇 가지 권장사항 설명합니다.
보안 및 환경
민감한 자격 증명 애플리케이션 코드에 직접 저장하면 버전 제어 시스템에 우발적으로 노출될 수 있습니다. 대신 환경 변수를 사용하여 연결 문자열, API 키 및 기타 민감한 정보를 저장 .
개발 환경의 경우 다음 도구를 사용하여 환경 변수를 관리 할 수 있습니다.
어떤 환경 변수 제어 도구를 선택하든 시크릿이 포함된 모든 파일(예: .env
, .envrc
등)을 .gitignore
파일 에 추가하여 버전 제어에 커밋되지 않도록 합니다.
프로덕션 배포의 경우 키 관리 시스템(KMS)을 사용합니다. 개발 환경에서 KMS 솔루션을 사용하여 보안을 강화할 수도 있습니다.
데이터베이스 연결 수명 주기
FastAPI 애플리케이션 스타트업 및 종료 이벤트에 대한 응답으로 클라이언트 연결을 초기화하고 닫아 MongoDB 연결 수명 주기를 올바르게 관리 . 이 접근 방식은 모듈 수준에서 연결을 초기화하는 것보다 더 강력합니다.
MongoDB 클라이언트 FastAPI 애플리케이션 객체 에 연결하여 코드베이스 전체의 모든 경로 작업 함수에서 액세스할 수 있도록 합니다. 이렇게 하면 전역 변수가 필요하지 않고 종속성 관리 간소화됩니다.
FastAPI의 수명 이벤트를 사용하여 연결 관리 처리하다 .
import os from contextlib import asynccontextmanager from logging import info from fastapi import FastAPI from pymongo import AsyncMongoClient async def db_lifespan(app: FastAPI): # Startup app.mongodb_client = AsyncMongoClient(os.environ["MONGODB_URL"]) app.database = app.mongodb_client.get_default_database() ping_response = await app.database.command("ping") if int(ping_response["ok"]) != 1: raise Exception("Problem connecting to database cluster.") else: info("Connected to database cluster.") yield # Shutdown await app.mongodb_client.close() app: FastAPI = FastAPI(lifespan=db_lifespan)
BSON 과 JSON 유형 처리
MongoDB 에 JSON 데이터를 제공하는 FastAPI 엔드포인트에는 JSON 에서 기본적으로 지원되지 않는 ObjectId
및 Binary
유형이 포함될 수 있습니다.
여러 가지 방법으로 ObjectId
를 직렬화할 수 있습니다.
문자열 기반 ID 사용:
_id
필드에 대해ObjectId
을 JSON 호환 문자열 값으로 바꿉니다. 이 접근 방식은 새 애플리케이션에는 적합할 수 있지만 기존 데이터가 있는 경우에는 적합하지 않을 수 있습니다.자동 변환:
ObjectId
값을 JSON 으로 직렬화할 때 문자열 표현으로 변환하고, 수신 데이터를 처리 때 문자열을 다시ObjectId
로 구문 분석합니다.Pydantic 통합: 이 튜토리얼의
PyObjectId
유형에 설명된 대로 Pydantic의 유형 주석을 사용하여 자동 변환을 처리하다 .객체문서 매퍼(ODM): Beanie와 같은 ODM을 사용하여 필드가 기본값
_id
으로 를ObjectId
사용한다고 가정하고 직렬화 및 역직렬화를 자동으로 처리합니다.
데이터 모델링
유연성을 유지하려면 데이터베이스 스키마 API 스키마 와 분리하세요. 이를 통해 API 인터페이스를 변경하지 않고도 MongoDB 문서 구조를 수정할 수 있습니다.
경로 작업에 Pydantic 클래스를 response_model
으로 제공하여 반환된 BSON 데이터의 필드를 변환, 유효성 검사, 문서 및 필터하다 . 다음 코드 예시 이 기술을 구현 방법을 보여 줍니다.
# A Pydantic class modelling the *response* schema. class Profile(BaseModel): """ A profile for a single user. """ id: Optional[str] = Field( default=None, description="MongoDB document ObjectID", alias="_id" ) username: str residence: str current_location: List[float] # A path operation that returns a Profile object as JSON. app = FastAPI() async def get_profile(profile_id: str) -> Mapping[str, Any]: # Uses response_model to automatically convert, validate, and document # the returned dict without manual Profile object creation. profile = await app.profiles.find_one({"_id": profile_id}) if profile is not None: # Return BSON document. FastAPI converts it automatically. return profile else: raise HTTPException( status_code=404, detail=f"No profile with id '{profile_id}'" )
더 많은 리소스
FastAPI 통합에 대한 자세한 내용은 다음 리소스를 참조하세요.
- MongoDB의 전체 스택 FastAPI 앱 생성기
지원 받거나 MongoDB Community 에 기여하려면 MongoDB 개발자 커뮤니티를 참조하세요.