이 문서의 과거 버전 (r1)을 보고 있습니다. 수정일: 2026.02.13 22:18
Python은 배우기 쉽고 읽기 쉬운 문법을 가진 고수준 인터프리터 언어이다. 범용 프로그래밍 언어로, 웹 개발, 데이터 분석, 인공지능, 과학 컴퓨팅 등 다양한 분야에서 널리 사용된다. 특히 명확한 코드 작성과 생산성을 중시하는 철학을 가지고 있다.
FastAPI는 Python을 위한 현대적이고 빠른 웹 프레임워크이다. 주로 API 서버를 구축하는 데 사용되며, 높은 성능과 개발 편의성을 제공하는 것이 특징이다. Starlette과 Pydantic을 기반으로 구축되어, 자동 문서 생성과 강력한 타입 검증 기능을 갖추고 있다.
이 프레임워크는 Python의 표준 타입 힌트를 적극 활용하여, 개발 단계에서 오류를 줄이고 코드의 가독성과 유지보수성을 높인다. 또한 비동기 프로그래밍을 완벽하게 지원하여, I/O 작업이 많은 현대적 애플리케이션의 성능을 극대화할 수 있다.
Python 생태계 내에서 FastAPI는 Flask의 간결함과 Django의 강력함 사이에서 균형을 잡은 프레임워크로 평가받는다. 마이크로서비스 아키텍처와 실시간 애플리케이션을 구축하는 데 특히 적합하다.
FastAPI는 Starlette와 Pydantic을 기반으로 구축된 현대적인 웹 프레임워크이다. 이 프레임워크는 빠른 개발 속도와 높은 런타임 성능을 동시에 제공하는 것을 주요 목표로 설계되었다. 파이썬의 표준 타입 힌트를 광범위하게 활용하여 직관적이고 에러 발생 가능성이 낮은 코드 작성을 가능하게 한다. 이는 마이크로서비스 아키텍처와 API 중심 개발에 특히 적합하다.
가장 두드러진 특징은 높은 성능과 비동기 지원이다. 내부적으로 비동기 웹 프레임워크인 Starlette를 사용하며, ASGI 표준을 완벽히 준수한다. 이를 통해 async/await 구문을 활용한 비동기 요청 처리가 가능하며, 동시성을 효율적으로 관리한다. 결과적으로 Node.js 및 Go로 작성된 API와 견줄 만한 처리량을 보여준다[1].
개발 편의성 측면에서는 자동으로 대화형 API 문서를 생성하는 기능이 있다. 애플리케이션을 실행하면 /docs 경로에서 Swagger UI 기반의 문서를, /redoc 경로에서 ReDoc 기반의 문서를 즉시 제공한다. 이 문서는 모든 엔드포인트, 매개변수, 요청 및 응답 모델을 실시간으로 반영하며, 브라우저에서 직접 API를 테스트해볼 수 있는 인터페이스를 포함한다.
타입 힌트와 데이터 검증은 Pydantic 라이브러리의 강력한 통합을 통해 이루어진다. 개발자는 파이썬 타입 어노테이션으로 요청과 응답의 데이터 구조를 정의하기만 하면, FastAPI가 자동으로 데이터의 유효성을 검사하고 직렬화/역직렬화를 처리한다. 이는 런타임 오류를 줄이고, 코드의 가독성과 유지보수성을 크게 향상시킨다.
FastAPI는 Starlette와 Pydantic을 기반으로 구축되어 높은 성능을 제공합니다. Starlette은 경량의 ASGI 웹 프레임워크로, FastAPI는 이를 활용하여 동기 및 비동기 요청을 모두 효율적으로 처리합니다. 이는 특히 I/O 바운드 작업(예: 데이터베이스 호출, 외부 API 요청)이 많은 현대적 웹 애플리케이션에서 큰 장점이 됩니다. 개발자는 async def 구문을 사용하여 비동기 경로 핸들러를 쉽게 정의할 수 있으며, 이를 통해 단일 스레드에서도 다수의 연결을 동시에 처리할 수 있습니다.
성능 측면에서 FastAPI는 Node.js 및 Go로 작성된 프레임워크와 견줄 만한 속도를 보입니다. 이는 내부적으로 uvloop를 사용하여 빠른 비동기 I/O를 구현하고, Pydantic을 통해 데이터 검증 로직이 순수 Python 코드로 실행되기 때문입니다. 아래 표는 TechEmpower의 벤치마크 결과를 요약한 것입니다[2].
프레임워크 | 언어 | 처리량 (Requests/sec) 범위 |
|---|---|---|
FastAPI | Python | 매우 높음 |
Node.js (Express) | JavaScript | 높음 |
Go (Gin) | Go | 매우 높음 |
Flask (동기) | Python | 중간 |
비동기 지원은 데이터베이스, 캐시, HTTP 클라이언트와 같은 외부 리소스와 상호작용할 때 그 진가를 발휘합니다. 예를 들어, SQLAlchemy의 비동기 버전(AsyncIO)이나 Databases 라이브러리와 함께 사용하면, 데이터베이스 쿼리 실행 중에도 애플리케이션이 다른 요청을 받아들일 수 있습니다. 이는 블로킹(동기) 방식에 비해 서버 자원 활용도를 극대화하고 전체적인 응답 시간을 단축시킵니다.
FastAPI는 애플리케이션을 실행하면 자동으로 대화형 API 문서를 생성하는 기능을 제공합니다. 이는 개발자가 별도의 문서 작성 작업 없이도 엔드포인트를 테스트하고 설명을 확인할 수 있게 해줍니다. 문서는 OpenAPI 표준을 준수하며, 코드에 작성된 타입 힌트와 Pydantic 모델, 함수의 독스트링을 기반으로 자동으로 구성됩니다.
애플리케이션을 실행한 후 기본적으로 /docs와 /redoc 두 가지 경로로 문서에 접근할 수 있습니다. /docs 경로는 Swagger UI를 제공하여 각 API 엔드포인트를 직접 호출해보고 응답을 즉시 확인할 수 있는 대화형 인터페이스를 보여줍니다. /redoc 경로는 ReDoc을 사용하여 보다 정리된 형태의 문서를 표시합니다.
문서 유형 | 접근 경로 | 사용 기술 | 주요 특징 |
|---|---|---|---|
대화형 API 문서 |
| 엔드포인트 직접 테스트 가능, 요청 매개변수 입력 폼 제공 | |
정적 API 문서 |
| 깔끔한 레이아웃의 읽기 전용 문서 |
이 자동 생성된 문서에는 경로 매개변수, 쿼리 매개변수, 요청 본문의 구조, 가능한 HTTP 상태 코드 및 응답 모델이 상세히 표시됩니다. 또한, 의존성 주입이 정의된 라우트의 경우 해당 의존성에 대한 요구사항도 문서에 자동으로 포함됩니다. 이 기능은 프론트엔드 개발자와의 협업을 용이하게 하고, API의 사양을 항상 최신 상태로 유지하도록 도와줍니다.
FastAPI는 Python의 타입 힌트를 적극적으로 활용하여 강력한 데이터 검증과 직렬화를 자동으로 제공합니다. 이는 개발자가 Pydantic 모델을 사용하여 요청과 응답의 데이터 구조를 명확히 정의할 수 있게 합니다. 정의된 모델은 들어오는 데이터의 유효성을 자동으로 검사하고, 잘못된 타입이나 누락된 필드가 있을 경우 자세한 오류 메시지를 반환합니다.
검증 과정은 요청 본문(Request Body), 경로 매개변수(Path Parameter), 쿼리 매개변수(Query Parameter) 모두에 적용됩니다. 예를 들어, 사용자 생성 API에서 UserCreate라는 Pydantic 모델을 정의하면, FastAPI는 들어오는 JSON 데이터가 모델의 필드 타입(예: str, int, EmailStr)과 제약 조건(예: Field(..., min_length=1))을 만족하는지 검증합니다. 검증에 실패하면 HTTP 상태 코드 422 Unprocessable Entity와 함께 각 필드별 오류 상세 정보를 응답합니다.
이 접근 방식의 주요 장점은 코드의 안정성과 가독성이 크게 향상된다는 점입니다. 함수의 매개변수에 타입 힌트와 Pydantic 모델을 사용함으로써, API의 입출력 계약이 코드 자체에 명시적으로 문서화됩니다. 이는 개발 중 실수를 줄이고, IDE의 자동 완성 기능을 지원하며, 생성된 API 문서(Swagger UI 및 ReDoc)에 정확한 스키마 정보를 제공합니다.
검증 대상 | 사용 방법 | 설명 |
|---|---|---|
요청 본문 |
|
|
경로 매개변수 | 함수 매개변수에 타입 힌트 사용 |
|
쿼리 매개변수 | 함수 매개변수에 타입 힌트와 기본값 사용 |
|
결과적으로, 타입 힌트 기반의 시스템은 런타임 오류를 사전에 방지하고, 보일러플레이트 검증 코드를 제거하여 개발 생산성을 높입니다. 이는 정적 타입 언어의 장점을 동적 타입 언어인 Python 생태계에 가져오는 혁신적인 방식으로 평가받습니다.
FastAPI를 사용하기 위해서는 Python 3.7 이상의 버전이 필요하다. 먼저 패키지 관리 도구인 pip를 사용하여 FastAPI와 ASGI 서버 역할을 하는 Uvicorn을 설치한다.
```bash
pip install fastapi uvicorn
```
필요에 따라 데이터 검증을 위한 Pydantic이나 데이터베이스 연동을 위한 SQLAlchemy 등의 추가 패키지를 함께 설치할 수 있다.
첫 번째 애플리케이션을 작성하려면 main.py와 같은 파이썬 파일을 생성하고 다음 코드를 작성한다.
```python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
```
애플리케이션을 실행하기 위해 터미널에서 다음 명령어를 사용한다. --reload 옵션은 코드 변경 시 서버를 자동으로 재시작하게 한다.
```bash
uvicorn main:app --reload
```
서버가 정상적으로 실행되면, 기본적으로 http://127.0.0.1:8000에서 애플리케이션에 접근할 수 있다. 브라우저에서 해당 주소를 열면 {"Hello": "World"}라는 JSON 응답을 확인할 수 있다. 또한 FastAPI가 자동으로 생성한 대화형 API 문서는 http://127.0.0.1:8000/docs에서 확인 가능하다.
FastAPI 애플리케이션 개발을 시작하려면 먼저 적절한 Python 환경과 필수 패키지를 설치해야 한다. 일반적으로 가상 환경을 생성하여 프로젝트 의존성을 격리하는 것이 권장된다. 다음 명령어를 사용하여 가상 환경을 만들고 활성화할 수 있다.
```bash
python -m venv venv
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activate
```
가상 환경이 활성화된 상태에서, 핵심 패키지인 fastapi와 서버 역할을 할 uvicorn을 설치한다. Uvicorn은 ASGI 서버로, FastAPI의 비동기 기능을 지원하기 위해 필요하다. 다음 pip 명령어로 설치를 진행한다.
```bash
pip install fastapi uvicorn
```
추가적으로 데이터 검증과 직렬화를 위한 Pydantic은 fastapi 패키지에 자동으로 포함되어 설치되지만, 데이터베이스 연동을 계획한다면 SQLAlchemy와 비동기 드라이버도 함께 설치하는 것이 일반적이다. 예를 들어, PostgreSQL과 비동기로 연동하려면 다음 패키지들을 추가로 설치할 수 있다.
```bash
pip install sqlalchemy asyncpg
```
필요한 패키지 설치 후, pip freeze > requirements.txt 명령어를 사용하여 설치된 패키지 목록을 파일로 저장하면 향후 환경 재구성이 용이해진다.
main.py라는 이름의 새 파일을 생성하고 다음 코드를 작성하여 시작할 수 있다.
```python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
```
이 애플리케이션은 두 개의 경로를 정의한다. 첫 번째 경로(/)는 GET 요청에 대해 간단한 JSON 응답을 반환한다. 두 번째 경로(/items/{item_id})는 경로 매개변수 item_id와 선택적 쿼리 매개변수 q를 사용한다. 타입 힌트(item_id: int)는 FastAPI가 자동으로 요청 데이터를 해당 타입으로 변환하고 검증하는 데 사용된다.
애플리케이션을 실행하려면 터미널에서 다음 Uvicorn 명령어를 사용한다.
```bash
uvicorn main:app --reload
```
--reload 옵션은 코드 변경 시 서버를 자동으로 재시작하게 한다. 서버가 실행되면, 기본적으로 http://127.0.0.1:8000에서 접근할 수 있다. 브라우저에서 해당 주소를 열면 {"Hello": "World"} 응답을 확인할 수 있다.
자동 생성된 대화형 API 문서는 http://127.0.0.1:8000/docs(Swagger UI) 또는 http://127.0.0.1:8000/redoc(ReDoc)에서 확인할 수 있다. 이 문서에서는 정의된 엔드포인트를 직접 테스트해볼 수 있다. 예를 들어, /docs 페이지에서 /items/{item_id} 경로를 찾아 item_id에 5를, q에 testquery를 입력하고 "Execute" 버튼을 클릭하면, 서버로부터 {"item_id":5,"q":"testquery"}와 같은 응답을 받게 된다.
FastAPI에서 라우팅은 데코레이터를 사용하여 정의한다. 각 경로는 특정 HTTP 메서드와 연결되며, 해당 경로로 들어오는 요청을 처리하는 함수를 지정한다. 기본적인 구조는 @app.get("/경로")와 같은 형태를 가진다.
요청에서 데이터를 추출하는 주요 방법은 경로 매개변수, 쿼리 매개변수, 요청 본문이다. 경로 매개변수는 URL 경로 자체에 포함된 값을 의미한다. 예를 들어, /users/{user_id}에서 {user_id} 부분이 해당하며, 함수의 매개변수로 동일한 이름을 선언하여 받는다. 쿼리 매개변수는 URL에서 ? 뒤에 key=value 형태로 전달된다. 함수 매개변수에 기본값을 할당하거나 None으로 설정하면 FastAPI는 이를 자동으로 쿼리 매개변수로 인식한다.
매개변수 유형 | 위치 | 예시 | 함수 매개변수 선언 |
|---|---|---|---|
경로 매개변수 | URL 경로 내 |
|
|
쿼리 매개변수 | URL |
|
|
요청 본문 데이터를 처리하기 위해 Pydantic 모델을 주로 사용한다. 클라이언트가 POST나 PUT 요청으로 보낸 JSON 데이터를 Pydantic 모델로 정의하면, FastAPI는 자동으로 데이터를 파싱하고 유효성을 검증한다. 또한, 잘못된 데이터 타입이 전송되면 자동으로 오류 응답을 반환한다. 여러 종류의 매개변수를 한 함수에서 혼합하여 사용하는 것도 가능하다.
예를 들어, 사용자 정보를 업데이트하는 엔드포인트는 경로 매개변수로 사용자 ID를, 요청 본문으로 새로운 데이터를 받을 수 있다. 이렇게 조합된 접근 방식은 복잡한 API 요청을 깔끔하고 타입 안전하게 처리할 수 있게 해준다.
FastAPI에서 클라이언트로부터 데이터를 받는 주요 방법은 경로 매개변수와 쿼리 매개변수를 사용하는 것이다. 경로 매개변수는 URL 경로 자체에 포함되는 변수이며, 쿼리 매개변수는 URL의 ? 뒤에 키=값 쌍으로 전달된다.
경로 매개변수를 정의하려면 경로 작성을 위한 데코레이터(예: @app.get("/items/{item_id}"))와 함수의 매개변수에서 동일한 이름을 사용한다. FastAPI는 자동으로 해당 위치의 값을 매개변수로 추출하여 함수에 전달한다. 매개변수의 타입을 타입 힌트(예: item_id: int)로 명시하면 자동으로 해당 타입으로 변환하고 검증한다. 만약 타입 변환이 실패하면 클라이언트에게 자동으로 오류 응답을 반환한다.
쿼리 매개변수는 함수 매개변수로 선언하되, 경로 매개변수에 해당하지 않는 모든 매개변수는 자동으로 쿼리 매개변수로 해석된다. 예를 들어, @app.get("/items/")와 함수 시그니처 def read_items(skip: int = 0, limit: int = 10):가 있다면, 요청 /items/?skip=20&limit=5는 skip=20, limit=5로 처리된다. 기본값을 할당하면 해당 매개변수는 선택 사항이 되며, 기본값이 없으면 필수 쿼리 매개변수가 된다.
다음은 두 가지 매개변수를 함께 사용하는 간단한 예시이다.
```python
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}/items")
async def read_user_item(
user_id: int, # 경로 매개변수
item_name: str, # 필수 쿼리 매개변수
q: str | None = None, # 선택적 쿼리 매개변수
short: bool = False # 선택적 쿼리 매개변수 (기본값 False)
):
item = {"item_name": item_name, "owner_id": user_id}
if q:
item.update({"q": q})
if not short:
item.update({"description": "This is a long description"})
return item
```
이 경우, /users/123/items?item_name=phone&q=search&short=true와 같은 요청을 처리할 수 있다.
FastAPI에서 클라이언트로부터 데이터를 받기 위해 HTTP POST, PUT, PATCH 메서드를 사용할 때, 요청 본문(request body)을 처리해야 한다. 요청 본문은 일반적으로 JSON 형식으로 전송된다. FastAPI는 Pydantic 라이브러리를 기반으로 한 모델을 사용하여 이 데이터를 선언적으로 정의하고, 강력한 검증, 직렬화, 문서화 기능을 제공한다.
요청 본문을 처리하려면 먼저 Pydantic의 BaseModel을 상속받은 데이터 모델을 정의해야 한다. 이 모델은 파이썬의 타입 힌트를 사용하여 각 필드의 데이터 타입과 선택 사항을 명시한다. 경로 연산 함수의 매개변수로 이 모델 타입을 선언하면, FastAPI는 들어오는 JSON 데이터를 자동으로 해당 모델의 인스턴스로 변환하고 검증한다. 필드가 선택적이면 기본값을 None으로 설정하거나 Optional 타입을 사용하며, 필수 필드는 그냥 타입을 명시한다.
모델 정의 예시 | 설명 |
|---|---|
| 필수 정수형 필드 |
| 필수 문자열 필드 |
| 필수 실수형 필드 |
| 선택적 불리언 필드 (기본값 None) |
이 모델은 데이터 검증에 핵심적인 역할을 한다. 예를 들어, int 타입으로 정의된 필드에 문자열이 전달되면 자동으로 변환을 시도하고, 불가능할 경우 명확한 오류 응답을 클라이언트에게 반환한다[3]. 또한, Field 함수를 사용하여 추가 제약 조건(예: price: float = Field(..., gt=0))을 설정할 수 있어, 가격이 0보다 커야 하는 등의 비즈니스 규칙을 쉽게 적용할 수 있다.
정의된 Pydantic 모델은 OpenAPI 스키마에 자동으로 통합되어, Swagger UI나 ReDoc에서 생성된 대화형 API 문서에 요청 본문의 예제 구조와 데이터 타입이 정확히 표시된다. 이는 클라이언트 개발자에게 명확한 가이드를 제공한다. 요청 본문과 경로/쿼리 매개변수를 동시에 사용해야 하는 경우, 경로 연산 함수에서 각각을 별도의 매개변수로 선언하면 FastAPI가 이를 올바르게 구분하여 처리한다.
의존성 주입은 FastAPI의 핵심 기능 중 하나로, 애플리케이션의 구성 요소 간 결합도를 낮추고 코드의 재사용성과 테스트 용이성을 높이는 디자인 패턴이다. FastAPI는 이 패턴을 공식적으로 지원하며, Depends() 함수를 사용하여 의존성을 선언적으로 정의하고 주입한다. 이를 통해 경로 처리 함수에서 데이터베이스 세션, 인증 정보, 설정 값 등 공통적으로 필요한 로직이나 객체를 쉽게 가져올 수 있다.
의존성 함수는 일반적인 Python 함수 또는 비동기 함수(async def)로 작성할 수 있다. 이 함수는 매개변수를 받을 수 있으며, FastAPI가 자동으로 해당 매개변수를 해결한다. 경로 처리 함수의 매개변수에 Depends(의존성_함수명)을 선언하면, FastAPI는 요청이 들어올 때마다 의존성 함수를 먼저 실행하고 그 반환값을 경로 처리 함수에 주입한다. 이 구조는 중복 코드를 제거하는 데 매우 효과적이다.
의존성 사용 사례 | 설명 |
|---|---|
공통 매개변수 검증 | 쿼리 파라미터나 헤더의 반복적 검증 로직을 의존성으로 분리한다. |
사용자 인증 | JWT 토큰을 검증하고 현재 사용자 정보를 반환하는 로직을 구현한다. |
데이터베이스 세션 관리 | 요청마다 데이터베이스 세션을 생성하고 트랜잭션을 관리한 후 자동으로 닫는다. |
역할 기반 접근 제어 | 사용자의 권한을 확인하여 특정 엔드포인트 접근을 제한한다. |
의존성은 계층적으로 구성될 수 있으며, 한 의존성 함수는 다른 의존성 함수에 의존할 수 있다. FastAPI는 이 의존성 그래프를 자동으로 해결한다. 또한 의존성의 반환값을 캐시하여 동일한 요청 내에서 여러 번 호출될 때 성능을 최적화할 수 있다. 이 메커니즘은 애플리케이션의 비즈니스 로직을 깔끔하게 유지하면서 인프라 관련 코드를 체계적으로 관리하는 데 기여한다.
의존성 함수는 FastAPI에서 특정 엔드포인트가 실행되기 전에 반드시 수행되어야 하는 공통 로직을 캡슐화하는 데 사용됩니다. 이 함수는 일반적인 파이썬 함수로 정의되며, Depends()를 사용하여 경로 작동 함수의 매개변수로 주입됩니다. 의존성 함수는 데이터베이스 세션 획득, 사용자 인증 확인, 요청 헤더 검증, 권한 확인 등 다양한 목적으로 활용됩니다.
의존성 함수는 매개변수를 받거나 다른 의존성 함수에 의존할 수 있습니다. FastAPI는 의존성 그래프를 분석하여 필요한 모든 의존성을 재귀적으로 해결합니다. 예를 들어, 사용자 인증을 위한 의존성 함수는 먼저 JWT 토큰을 검증하는 의존성 함수에 의존할 수 있습니다. 의존성 함수의 반환 값은 경로 작동 함수에 직접 전달되거나, 반환 값이 필요 없는 경우 단순히 로직 실행만을 위해 사용될 수 있습니다.
다음은 데이터베이스 세션을 제공하는 간단한 의존성 함수의 예시입니다.
```python
from typing import Annotated
from fastapi import Depends
from sqlalchemy.orm import Session
from .database import get_db
# 'get_db'는 데이터베이스 세션을 생성하고 종료하는 제너레이터 함수라고 가정
def get_database_session(db: Annotated[Session, Depends(get_db)]):
return db
```
보다 복잡한 예로, 쿼리 매개변수와 헤더를 검증하는 의존성 함수를 작성할 수 있습니다.
```python
from typing import Annotated, Optional
from fastapi import Depends, Header, HTTPException, Query
def verify_common_params(
x_api_key: Annotated[Optional[str], Header()] = None,
q: Annotated[Optional[str], Query(max_length=50)] = None,
):
if not x_api_key:
raise HTTPException(status_code=400, detail="X-API-Key header is missing")
if q and "admin" in q:
raise HTTPException(status_code=403, detail="Query contains restricted word")
return {"api_key": x_api_key, "query": q}
```
이 함수는 X-API-Key 헤더의 존재를 확인하고, 쿼리 매개변수 q에 특정 금지어가 포함되었는지 검사합니다. 검증을 통과하면 관련 정보를 딕셔너리로 반환하여 경로 함수에서 사용할 수 있게 합니다.
의존성 주입을 활용하면 여러 라우팅 핸들러에서 공통적으로 필요한 로직을 중복 없이 재사용할 수 있다. 이를 통해 코드의 일관성을 유지하고 유지보수성을 높일 수 있다. 예를 들어, 데이터베이스 세션 획득, 사용자 인증 확인, 특정 권한 검사, 요청 로깅 등의 작업은 대표적인 공통 로직이다.
공통 로직은 Depends() 데코레이터를 사용하는 함수로 정의한다. 이 함수는 필요한 매개변수를 받고, 공통 작업을 수행한 후 결과를 반환한다. 라우터에서는 이 의존성 함수를 매개변수로 선언하기만 하면, FastAPI가 자동으로 해당 함수를 실행하고 그 결과를 핸들러에 주입한다. 아래는 데이터베이스 세션을 제공하는 공통 의존성의 예시이다.
```python
from fastapi import Depends
from sqlalchemy.orm import Session
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get("/items/")
async def read_items(db: Session = Depends(get_db)):
# db 세션을 사용한 작업
return db.query(Item).all()
```
보다 복잡한 시나리오에서는 의존성 함수가 다른 의존성 함수에 의존하는 체인을 형성할 수 있다. 이는 로직을 모듈화하고 세분화하는 데 유용하다. 예를 들어, get_current_user 의존성은 get_db에 의존하여 데이터베이스에서 사용자를 조회하고, get_current_active_user는 다시 get_current_user에 의존하여 활성 사용자만을 필터링할 수 있다. 이렇게 구성하면 각 의존성은 단일 책임을 가지며, 조합을 통해 복잡한 요구사항을 깔끔하게 처리한다.
FastAPI 애플리케이션에서 데이터를 영구적으로 저장하고 관리하기 위해 데이터베이스 연동은 필수적이다. FastAPI는 ORM 라이브러리인 SQLAlchemy와의 통합을 공식적으로 지원하며, 비동기 처리를 위한 SQLAlchemy의 비동기 엔진을 활용할 수 있다. 이를 통해 데이터베이스 쿼리 작업이 애플리케이션의 메인 이벤트 루프를 차단하지 않고 효율적으로 수행된다.
데이터베이스 모델은 일반적으로 SQLAlchemy ORM의 Base 클래스를 상속받아 정의한다. 각 클래스 속성은 데이터베이스 테이블의 컬럼에 매핑된다. 연결 설정은 비동기 엔진(AsyncEngine), 세션 생성기(async_sessionmaker), 그리고 Base 클래스를 선언하는 것으로 구성된다. FastAPI의 의존성 주입 시스템을 사용하면 요청마다 데이터베이스 세션을 생성하고 트랜잭션을 관리하는 공통 로직을 쉽게 재사용할 수 있다.
비동기 데이터베이스 접근은 async/await 문법을 사용한다. 쿼리 실행 시 session.execute()와 같은 메서드를 await 키워드와 함께 호출해야 한다. 이를 통해 I/O 바운드 작업 동안 애플리케이션이 다른 요청을 처리할 수 있어 성능이 향상된다. 주로 사용되는 비동기 드라이버로는 PostgreSQL용 asyncpg와 SQLite용 aiosqlite가 있다.
구성 요소 | 설명 | 비동기 사용 예시 |
|---|---|---|
엔진( | 데이터베이스에 대한 연결 풀을 관리한다. |
|
세션 로컬( | 데이터베이스 세션을 생성하는 팩토리이다. |
|
모델 클래스 | Python 클래스로 데이터베이스 테이블 구조를 정의한다. |
|
의존성 함수 | 요청마다 새 세션을 제공하고 트랜잭션을 관리한다. |
|
연동 시 주의할 점은 모든 데이터베이스 관련 코드(모델 정의, 쿼리, 세션 관리)가 비동기 방식으로 일관되게 작성되어야 한다는 것이다. 동기식 ORM 함수를 사용하면 애플리케이션이 차단될 수 있다. 또한, Alembic 같은 도구를 이용한 비동기 마이그레이션 설정이 필요하다.
SQLAlchemy는 파이썬에서 널리 사용되는 ORM 라이브러리이다. FastAPI 애플리케이션에서 SQLAlchemy를 사용하면 관계형 데이터베이스를 객체 지향적으로 다룰 수 있다. 이를 통해 데이터베이스 테이블을 파이썬 클래스로 정의하고, 복잡한 SQL 쿼리 대신 직관적인 파이썬 코드로 데이터를 조작할 수 있다.
FastAPI와 SQLAlchemy를 통합하는 일반적인 접근 방식은 애플리케이션의 데이터베이스 모델, 세션 관리, 연결 풀을 설정하는 것이다. 먼저 sqlalchemy와 sqlalchemy.orm을 임포트하여 데이터베이스 모델 클래스를 Base = declarative_base()를 상속받아 정의한다. 데이터베이스 연결은 create_engine 함수를 사용하며, 세션 관리는 sessionmaker를 통해 설정한다. FastAPI의 의존성 주입 시스템은 요청마다 독립적인 데이터베이스 세션을 생성하고 종료하는 데 유용하게 활용된다.
비동기 작업을 위해서는 sqlalchemy.ext.asyncio 모듈을 사용한다. create_async_engine으로 비동기 엔진을 생성하고, async_sessionmaker로 비동기 세션을 설정한다. 데이터베이스 작업은 async with 문과 함께 await를 사용하여 수행한다. 이는 ASGI 서버와 호환되어 I/O 대기 시간 동안 다른 요청을 처리할 수 있게 하여 애플리케이션의 전체 처리량을 높인다.
구성 요소 | 설명 | 비동기 지원 시 사용 클래스 |
|---|---|---|
엔진(Engine) | 데이터베이스에 대한 연결 풀과 다이얼렉트를 관리한다. |
|
세션(Session) | 객체를 추가, 수정, 삭제하고 쿼리를 실행하는 작업의 단위이다. |
|
모델(Model) | 데이터베이스 테이블의 구조를 정의하는 파이썬 클래스이다. |
|
이러한 통합을 통해 개발자는 강력한 타입 검증과 자동 문서화를 제공하는 FastAPI의 Pydantic 모델과 데이터베이스 계층을 담당하는 SQLAlchemy 모델을 명확히 분리하여 유지보수성 높은 코드를 작성할 수 있다.
FastAPI는 Starlette와 Pydantic을 기반으로 구축되어, 비동기 프로그래밍을 핵심적으로 지원합니다. 이 특징은 데이터베이스 접근 시 특히 중요한 이점을 제공합니다. 동기식 코드에서 데이터베이스 쿼리 실행은 응답을 받을 때까지 스레드가 블로킹되지만, 비동기 방식은 쿼리가 실행되는 동안 애플리케이션이 다른 작업을 처리할 수 있게 합니다. 이를 통해 적은 수의 서버 리소스로 더 많은 동시 연결을 효율적으로 처리할 수 있습니다. FastAPI에서 비동기 데이터베이스 작업을 구현하려면, 비동기 드라이버를 지원하는 데이터베이스 라이브러리(예: asyncpg for PostgreSQL, aiomysql for MySQL)와 비동기 호환 ORM인 SQLAlchemy의 비동기 확장인 SQLAlchemy asyncio를 함께 사용하는 것이 일반적입니다.
비동기 데이터베이스 세션을 구성하는 기본 패턴은 다음과 같습니다. 먼저, asyncpg와 같은 비동기 드라이버를 사용하는 데이터베이스 연결 URL을 설정합니다. 그 후, create_async_engine 함수로 비동기 엔진을 생성하고, async_sessionmaker를 사용하여 비동기 세션 팩토리를 만듭니다. 이 세션은 의존성 주입을 통해 라우트 핸들러 함수에 제공될 수 있습니다. 핸들러 함수는 async def로 선언되고, 내부에서 async with 문을 사용하여 데이터베이스 세션을 획득한 후, await session.execute()와 같은 메서드로 비동기 쿼리를 실행합니다.
접근 방식 | 사용 라이브러리 | 주요 특징 |
|---|---|---|
비동기 ORM | SQLAlchemy asyncio + asyncpg/aiomysql | 선언적 모델 정의, 세션 관리, 복잡한 쿼리 작성에 유리합니다. |
비동기 쿼리 빌더 | databases[4] | SQLAlchemy Core와 유사한 구문으로, 더 가벼운 추상화를 제공합니다. |
원시 SQL | asyncpg, aiomysql 직접 사용 | 최고의 성능이 필요하거나 ORM 오버헤드를 피하고자 할 때 사용합니다. |
비동기 작업을 수행할 때는 몇 가지 주의사항이 있습니다. 모든 데이터베이스 관련 호출 앞에 await 키워드를 명시적으로 붙여야 합니다. 또한, 동기식 라이브러리(예: 기존의 동기 SQLAlchemy 세션, 표준 라이브러리의 json 모듈 대신 orjson[5] 사용)를 비동기 컨텍스트 내에서 블로킹 없이 사용하려면 주의가 필요합니다. 일반적으로 asyncio.to_thread()를 이용해 별도 스레드에서 실행하거나, 해당 작업의 비동기 대체 라이브러리를 찾는 것이 좋습니다. 이러한 패턴을 올바르게 적용하면, I/O 바운드 작업이 많은 현대적 웹 API의 처리량과 응답성을 크게 향상시킬 수 있습니다.
JWT는 JSON 형식의 정보를 안전하게 전송하기 위한 개방형 표준이다. FastAPI는 python-jose와 passlib 같은 라이브러리와 쉽게 통합되어 JWT를 이용한 인증 흐름을 구현할 수 있다. 일반적인 구현 방식은 사용자가 로그인 시 유효한 자격 증명을 제출하면 서버가 서명된 액세스 토큰을 생성하여 응답한다. 이후 클라이언트는 이 토큰을 HTTP 요청의 Authorization 헤더에 담아 보내고, 서버는 토큰의 서명과 유효성을 검증하여 요청을 처리한다. 토큰 만료 시 리프레시 토큰을 사용하여 새로운 액세스 토큰을 발급받는 방식도 일반적이다.
FastAPI는 OAuth2와 OpenID Connect 표준을 내장 지원한다. fastapi.security 모듈은 OAuth2PasswordBearer와 같은 클래스를 제공하여 표준 준수 보안 스키마를 쉽게 설정할 수 있게 한다. 이를 통해 패스워드 흐름 같은 일반적인 인가 방식을 구현할 수 있다. 또한, Pydantic 모델을 활용하면 요청 본문의 사용자 이름과 비밀번호에 대한 데이터 검증을 자동으로 수행할 수 있다.
보안을 강화하기 위해 비밀번호는 반드시 단방향 해시 함수로 암호화하여 저장해야 한다. 토큰 서명에는 충분히 강력한 비밀 키를 사용해야 하며, HTTPS를 통한 통신은 필수적이다. 민감한 작업을 수행하는 경로에는 의존성 주입을 통해 토큰 검증 로직을 적용하여 인증된 사용자만 접근할 수 있도록 제한한다.
JWT는 JSON 형식의 정보를 안전하게 전송하기 위한 개방형 표준(RFC 7519)이다. FastAPI에서 JWT 기반 인증을 구현하려면 일반적으로 pyjwt 또는 python-jose와 같은 라이브러리를 사용하여 토큰을 생성하고 검증한다. 인증 흐름은 클라이언트가 사용자 자격 증명(예: 사용자명과 비밀번호)으로 로그인 요청을 보내면, 서버가 이를 검증한 후 서명된 JWT를 발급하여 응답한다. 이후 클라이언트는 이 토큰을 HTTP 요청의 Authorization 헤더에 담아 보내고, 서버는 토큰의 서명과 유효성을 검사하여 요청을 처리할지 결정한다.
구현의 핵심은 토큰 생성과 검증을 담당하는 의존성 함수를 만드는 것이다. 다음은 간단한 예시 코드의 구조이다.
```python
from jose import JWTError, jwt
from passlib.context import CryptContext
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def create_access_token(data: dict):
to_encode = data.copy()
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(status_code=401, detail="Invalid credentials")
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
return username
```
보안을 강화하기 위해 비밀번호는 반드시 bcrypt나 scrypt 같은 안전한 해시 알고리즘으로 암호화하여 저장해야 한다. 또한, 토큰에는 만료 시간(exp)을 명시적으로 포함시키는 것이 일반적이다. FastAPI의 OAuth2PasswordBearer를 사용하면 OpenAPI 문서에 인증 스키마를 자동으로 통합할 수 있어 개발 편의성이 높아진다.
고려 사항 | 설명 |
|---|---|
토큰 서명에 사용되며, 예측 불가능한 강력한 문자열이어야 한다. | |
토큰 만료 | 짧은 유효 기간을 설정하고, Refresh Token을 활용하여 보안을 강화한다. |
토큰 저장 | 클라이언트 측에서는 localStorage보다 HttpOnly 쿠키에 저장하는 것이 XSS 공격에 더 안전하다[6]. |
알고리즘 |
OAuth 2.0은 제3자 애플리케이션이 사용자의 자원에 제한적으로 접근할 수 있도록 허용하는 인가 프레임워크이다. FastAPI는 내장 보안 유틸리티를 통해 OAuth2의 여러 그랜트 타입(Grant Type)을 쉽게 구현할 수 있도록 지원한다. 특히 자주 사용되는 패스워드 플로우(Resource Owner Password Credentials Flow)와 인가 코드 플로우(Authorization Code Flow)를 OAuth2PasswordBearer 및 OAuth2AuthorizationCodeBearer 같은 클래스를 활용해 설정할 수 있다. 보안 스키마는 OpenAPI 명세에 자동으로 통합되어 생성된 API 문서에서 직접 인증을 테스트할 수 있게 한다.
FastAPI의 보안 모듈(fastapi.security)은 다양한 보안 스키마를 제공한다. OAuth2PasswordBearer는 토큰을 검색할 URL을 지정하여 사용하며, 의존성 주입 시스템과 결합해 라우트에서 쉽게 현재 사용자를 검증하는 데 사용된다. HTTP 기본 인증(HTTP Basic), API 키(API Key, 예: 쿼리 파라미터나 헤더), 베어러 토큰(Bearer Token, JWT용) 등을 위한 스키마도 별도로 제공된다. 이러한 스키마들은 Pydantic 모델과 호환되어 요청 데이터의 검증과 보안 처리를 한 번에 관리할 수 있다.
다음은 FastAPI에서 OAuth2 패스워드 플로우와 JWT를 결합한 간단한 보안 스키마 설정 예시이다.
```python
from fastapi import Depends, FastAPI, HTTPException
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
# ... JWT 관련 라이브러리 및 사용자 검증 로직 임포트
app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
# 사용자 이름(form_data.username)과 비밀번호(form_data.password) 검증
# 검증 성공 시 JWT 액세스 토큰 생성 및 반환
return {"access_token": access_token, "token_type": "bearer"}
@app.get("/users/me")
async def read_users_me(token: str = Depends(oauth2_scheme)):
# 의존성 주입된 oauth2_scheme이 자동으로 Authorization 헤더에서 토큰을 추출
# JWT 토큰 검증 및 사용자 정보 반환
return user
```
보안을 강화하기 위해 HTTPS 사용은 필수적이다. 또한, 토큰의 만료 시간을 짧게 설정하고, 리프레시 토큰을 활용하는 패턴을 적용하는 것이 좋다. 민감한 작업을 수행하는 라우트에는 추가적인 권한 검사(권한 부여(Authorization)) 로직을 의존성으로 구현하여 접근을 세밀하게 제어할 수 있다.
FastAPI 애플리케이션의 안정성을 보장하기 위해 단위 테스트와 디버깅은 필수적인 단계이다. FastAPI는 pytest와 같은 인기 있는 테스트 프레임워크와의 통합을 완벽하게 지원하여 테스트 작성을 용이하게 한다. TestClient 클래스를 사용하면 실제 서버를 실행하지 않고도 애플리케이션의 엔드포인트를 호출하고 응답을 검증할 수 있다. 테스트는 일반적으로 경로 함수, 의존성 주입, 데이터 검증 로직이 예상대로 동작하는지 확인하는 데 중점을 둔다.
디버깅 과정에서는 Uvicorn과 같은 ASGI 서버의 내장 디버깅 기능이나 PyCharm, Visual Studio Code 같은 IDE의 디버거를 활용할 수 있다. 애플리케이션 실행 시 --reload 플래그를 사용하면 코드 변경 사항을 자동으로 감지하여 재시작하므로 개발 속도를 높일 수 있다. 또한, FastAPI는 유효하지 않은 요청이나 서버 내부 오류 발생 시 자세한 오류 정보를 포함한 구조화된 응답을 반환하여 문제의 원인을 빠르게 파악하는 데 도움을 준다.
테스트와 디버깅을 위한 일반적인 접근법은 다음 표와 같이 정리할 수 있다.
구분 | 주요 도구/기법 | 목적 |
|---|---|---|
단위 테스트 |
| 개별 경로 연산자와 의존성의 논리적 정확성을 검증 |
통합 테스트 |
| 여러 컴포넌트 간의 상호작용과 데이터베이스 연동을 검증 |
디버깅 | IDE 디버거, | 런타임 오류의 원인을 식별하고 코드 흐름을 분석 |
예외 처리 | FastAPI 예외 핸들러, 커스텀 HTTPException | 사용자에게 명확한 오류 메시지를 제공하고 애플리케이션 상태를 보호 |
효율적인 테스트 스위트를 구성하고 체계적인 디버깅 절차를 확립하는 것은 장기적으로 코드 품질을 유지하고 유지보수 비용을 절감하는 데 결정적인 역할을 한다.
단위 테스트는 FastAPI 애플리케이션의 개별 구성 요소, 즉 경로 작업 함수나 유틸리티 함수 등이 예상대로 동작하는지 검증하는 과정이다. FastAPI는 pytest와 완벽하게 호환되며, TestClient 클래스를 제공하여 실제 서버를 실행하지 않고도 API 엔드포인트를 테스트할 수 있게 한다. 테스트는 일반적으로 test_ 접두사로 시작하는 파일이나 함수에 작성한다.
TestClient를 사용한 기본적인 테스트는 다음과 같은 구조를 가진다. 먼저, FastAPI 애플리케이션 인스턴스를 임포트하고 TestClient로 감싼다. 그 후, client 객체를 사용해 HTTP 요청을 보내고 응답 상태 코드, JSON 데이터 등을 검증한다.
```python
from fastapi.testclient import TestClient
from main import app # main.py에 정의된 FastAPI 앱
client = TestClient(app)
def test_read_main():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Hello World"}
```
의존성 주입이 사용된 경로를 테스트할 때는 의존성을 재정의(override)하는 것이 일반적이다. 이를 통해 데이터베이스나 외부 서비스에 의존하지 않고 테스트용 가짜(mock) 객체나 함수를 주입할 수 있다. app.dependency_overrides를 사용하면 애플리케이션 수준에서 의존성을 쉽게 교체할 수 있다.
테스트 대상 | 주요 도구/기법 | 검증 예시 |
|---|---|---|
일반 경로 작업 |
| 상태 코드, 응답 본문 |
의존성 주입 |
| 모의 객체 동작 검증 |
데이터 검증 오류 |
|
|
비동기 함수 |
| 비동기 함수 직접 호출 |
테스트는 데이터베이스와의 연동을 포함할 경우 더 복잡해진다. 이를 위해 테스트용 데이터베이스를 별도로 설정하거나, SQLAlchemy의 메모리 데이터베이스를 활용하는 것이 일반적이다. 각 테스트 함수가 독립적으로 실행되도록, 테스트 전후에 데이터베이스를 초기화하는 픽스처(fixture)를 사용하는 것이 좋다. 이렇게 작성된 단위 테스트는 코드 변경 시 발생할 수 있는 회귀(regression) 오류를 빠르게 발견하는 안전망 역할을 한다.
FastAPI 애플리케이션의 디버깅은 내장된 디버깅 도구와 외부 라이브러리를 활용하여 효율적으로 수행할 수 있다. 기본적으로 uvicorn 서버를 실행할 때 --reload 플래그를 사용하면 코드 변경 시 자동으로 애플리케이션을 재시작하여 개발 과정을 용이하게 한다. 더 나아가 Python의 표준 라이브러리인 pdb나 외부 패키지인 ipdb를 이용하여 비동기 코드 내부에 중단점을 설정하고 변수 상태를 단계별로 검사할 수 있다.
에러 발생 시 FastAPI는 자세한 추적 정보를 포함한 표준화된 JSON 형식의 오류 응답을 반환한다. 개발 환경에서는 이 정보를 통해 문제의 근본 원인을 빠르게 파악할 수 있다. 또한, 로깅을 구성하여 애플리케이션의 실행 흐름과 예외 사항을 기록하는 것이 중요하다. Python의 logging 모듈을 사용하거나, 구조화된 로깅을 제공하는 structlog 같은 라이브러리를 통합할 수 있다.
도구/기법 | 주요 용도 | 비고 |
|---|---|---|
| 코드 변경 감지 및 자동 재시작 | 개발 환경 전용 |
| 대화형 디버깅 및 중단점 설정 | 비동기 코드 디버깅 지원 |
FastAPI 예외 핸들러 | 사용자 정의 오류 응답 생성 |
|
로깅 ( | 애플리케이션 이벤트 및 오류 기록 | 로그 레벨 설정 가능 |
외부 모니터링 도구를 연동하는 것도 디버깅과 성능 분석에 도움이 된다. 예를 들어, Sentry는 실시간으로 애플리케이션 오류를 추적하고 알림을 제공한다. Prometheus와 Grafana를 결합하면 요청 처리 시간, 오류율 같은 런타임 메트릭을 시각화하여 성능 병목 현상을 발견할 수 있다. 이러한 도구들은 운영 환경에서 발생하는 복잡한 문제를 해결하는 데 필수적이다.
애플리케이션을 Docker 컨테이너로 패키징하는 것은 일관된 실행 환경을 보장하고 배포를 단순화하는 표준 방법이다. 일반적으로 Dockerfile을 작성하여 Python 기본 이미지에서 시작하고, 의존성을 설치한 후 애플리케이션 코드를 복사한다. FastAPI 애플리케이션의 경우 Uvicorn이나 Hypercorn과 같은 ASGI 서버를 사용하여 컨테이너 내에서 실행한다. 다중 컨테이너 구성(예: 애플리케이션, 데이터베이스, 리버스 프록시)은 Docker Compose를 통해 관리할 수 있다. 컨테이너 이미지는 Docker Hub, Amazon ECR, Google Container Registry와 같은 레지스트리에 푸시되어 클라우드 플랫폼이나 쿠버네티스 클러스터에서 배포된다.
운영 환경에서는 애플리케이션의 성능과 상태를 지속적으로 모니터링하는 것이 중요하다. 주요 지표에는 요청 처리량(RPS), 응답 지연 시간(Latency), 오류율, 그리고 서버의 CPU 및 메모리 사용량이 포함된다. 이러한 지표는 Prometheus와 같은 모니터링 시스템과 Grafana 대시보드를 통해 수집 및 시각화할 수 있다. FastAPI는 /metrics 엔드포인트를 통해 기본적인 메트릭을 노출할 수 있으며, 더 상세한 모니터링을 위해 OpenTelemetry와 같은 분산 추적 도구를 통합할 수도 있다. 로그는 구조화된 형식(예: JSON)으로 출력하고 ELK 스택이나 Sentry 같은 중앙 집중식 로그 관리 시스템으로 전송하여 분석한다.
도구/기술 카테고리 | 예시 | 주요 용도 |
|---|---|---|
컨테이너화 및 오케스트레이션 | 애플리케이션 패키징, 배포, 스케일링 관리 | |
모니터링 및 메트릭 | 성능 지표 수집, 시각화, 분산 추적 | |
로그 관리 | 중앙 집중식 로그 수집, 분석, 오류 추적 | |
배포 플랫폼 | 클라우드 인프라 호스팅 및 관리 |
FastAPI 애플리케이션을 Docker 컨테이너로 패키징하는 것은 애플리케이션과 그 모든 의존성을 이식 가능하고 일관된 환경에 포함시켜 배포와 운영을 단순화합니다. 이를 위해 Dockerfile이라는 텍스트 파일을 작성하여 컨테이너 이미지를 빌드하는 방법을 정의합니다. 일반적인 FastAPI 애플리케이션의 Dockerfile은 공식 Python 이미지를 기반으로 하며, 작업 디렉토리를 설정하고 의존성을 설치한 후, Uvicorn과 같은 ASGI 서버를 사용해 애플리케이션을 실행합니다.
다음은 FastAPI 애플리케이션을 위한 기본적인 Dockerfile의 예시입니다.
```dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
```
이미지를 빌드하고 실행하는 과정은 아래와 같습니다.
단계 | 명령어 | 설명 |
|---|---|---|
이미지 빌드 |
| 현재 디렉토리의 |
컨테이너 실행 |
| 빌드된 이미지로부터 컨테이너를 백그라운드에서 실행하고, 호스트의 8000번 포트를 컨테이너의 8000번 포트에 매핑합니다. |
운영 환경에서는 단일 컨테이너 실행보다는 Docker Compose를 사용하는 것이 일반적입니다. docker-compose.yml 파일을 통해 애플리케이션 서비스와 필요한 데이터베이스, 캐시 서비스 등을 함께 정의하고 관리할 수 있습니다. 또한, 멀티스테이지 빌드를 활용하면 최종 이미지의 크기를 줄일 수 있으며, 프로덕션에서는 Gunicorn과 같은 프로세스 매니저와 함께 Uvicorn 워커를 사용하는 것이 성능과 안정성 측면에서 권장됩니다[7]. 컨테이너화된 애플리케이션은 Kubernetes나 클라우드 플랫폼의 컨테이너 서비스에 배포하여 확장성과 가용성을 높일 수 있습니다.
애플리케이션의 성능을 지속적으로 관찰하고 분석하는 과정을 의미한다. 이는 응답 시간, 처리량, 에러율, 자원 사용률 같은 핵심 지표를 추적하여 시스템의 건강 상태를 파악하고 병목 현상을 사전에 발견하는 데 목적이 있다.
주요 모니터링 지표와 도구는 다음과 같이 정리할 수 있다.
지표 카테고리 | 주요 측정 항목 | 일반적인 도구 예시 |
|---|---|---|
애플리케이션 성능 | 요청당 지연 시간, 초당 요청 수(RPS), 에러율 | |
시스템 자원 | CPU 사용률, 메모리 사용량, 디스크 I/O, 네트워크 대역폭 | 운영 체제 기본 도구(htop, vmstat), cAdvisor |
비즈니스 로직 | 핵심 API 엔드포인트 성능, 데이터베이스 쿼리 성능 | 커스텀 메트릭, SQLAlchemy 이벤트 리스너 |
구현 시에는 ASGI 서버의 내장 로그나 미들웨어를 활용해 요청-응답 사이클 시간을 측정할 수 있다. 또한, Prometheus 클라이언트 라이브러리를 사용하여 커스텀 지표를 노출시키고, 이를 Grafana 대시보드에서 시각화하는 것이 일반적인 방법이다. 데이터베이스 쿼리 성능은 SQLAlchemy의 echo=True 옵션이나 더 정교한 프로파일링 도구로 모니터링한다.
효과적인 모니터링을 위해서는 정상 상태의 기준치를 설정하고, 임계값을 초과할 경우 알림을 발송하는 경고 규칙을 구성해야 한다. 이를 통해 성능 저하나 장애 발생 시 신속하게 대응할 수 있다. 모니터링 데이터는 단순한 현황 파악을 넘어, 시스템 확장 필요성 판단이나 코드 최적화의 근거로도 활용된다.