파이썬 웹 프레임워크 FastAPI
FastAPI는 최근에 인기를 끌고 있는 파이썬 웹 프레임워크 중 하나입니다. FastAPI는 데코레이터와 타입 어노테이션을 활용해 빠르고 안전한 RESTful API를 만들 수 있게 해줍니다.
FastAPI는 다른 파이썬 웹 프레임워크와 비교했을 때 훨씬 빠르게 동작하며, 견고하고 안정적인 코드를 작성할 수 있습니다. 이는 Pydantic이라는 패키지를 내부적으로 사용하기 때문입니다. Pydantic은 데이터 유효성 검사, 타입 확인 및 데이터 직렬화를 담당하는 모델 검증 도구입니다.
FastAPI는 또한 OpenAPI 및 JSON Schema를 자동으로 생성하여 문서화를 제공해주며, Swagger UI 및 Redoc을 지원합니다. 이를 통해 개발자들은 API의 동작 방식과 요청/응답 모델을 쉽게 이해하고 사용할 수 있습니다.
또한 FastAPI는 ASGI(Application Server Gateway Interface)를 내부적으로 지원하기 때문에 비동기 프로그래밍도 지원합니다. 이는 동시성 처리 및 대규모 동시 요청을 처리할 수 있게 해줍니다.
FastAPI는 기본적으로 Python 3.7+을 지원하며, 간단한 코드로 API를 작성할 수 있습니다. 각각의 경로(handler)는 별도의 함수로 정의되며, Pydantic 모델을 이용해 요청과 응답 데이터를 자동으로 검증합니다.
마지막으로 FastAPI는 높은 생산성과 코드 재사용성을 제공합니다. 예를 들어, FastAPI를 사용하면 CRUD(Create, Read, Update, Delete) API를 작성하는 데 드는 노력을 줄일 수 있습니다. 이는 FastAPI가 SQLAlchemy와 연계하여 CRUD 기능을 제공하기 때문입니다.
FastAPI는 현재도 개발이 계속되고 있으며, 많은 기능들이 추가될 예정입니다. 따라서 파이썬 RESTful API를 구축하는 개발자들에게는 FastAPI가 좋은 선택일 수 있습니다.
FastAPI 설치
FastAPI를 사용하기 위해서는 우선 FastAPI 패키지를 설치해야 합니다. pip를 이용하여 다음과 같이 설치할 수 있습니다.
pip install fastapi
FastAPI를 사용하기 위해서는 추가로 uvicorn 패키지도 설치해야 합니다. uvicorn은 FastAPI에서 기본적으로 사용되는 ASGI 서버입니다. 다음과 같이 설치할 수 있습니다.
pip install uvicorn
간단한 API 예제
간단한 FastAPI 애플리케이션을 만들어보겠습니다. 다음과 같은 코드를 작성해보세요.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
위 코드에서 @app.get("/") 데코레이터는 "/" 경로로 GET 요청이 들어올 경우 read_root() 함수를 호출한다는 것을 의미합니다. read_root() 함수는 JSON 형태의 {"Hello": "World"} 응답을 반환합니다.
이제 위 코드를 저장한 후, 다음과 같이 uvicorn 명령어를 이용하여 애플리케이션을 실행해보세요.
uvicorn main:app --reload
위 명령어는 main 모듈의 app 변수에 저장된 FastAPI 애플리케이션을 실행하는 것입니다. --reload 옵션을 주면 코드가 변경될 때마다 서버를 자동으로 재시작합니다.
애플리케이션을 실행한 후, 브라우저나 curl 명령어를 이용하여 http://127.0.0.1:8000/ 에 접속해보세요. JSON 형태의 응답이 출력되는 것을 확인할 수 있습니다.
Path Parameters 사용하기
FastAPI는 경로 매개변수를 사용하여 URL에서 변수를 추출할 수 있습니다. 다음과 같은 코드를 작성해보세요.
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
def read_item(item_id: int):
return {"item_id": item_id}
위 코드에서 {item_id}는 경로 매개변수를 의미합니다. read_item() 함수의 매개변수 item_id는 경로 매개변수에서 추출된 변수입니다. 이제 다음과 같은 URL로 요청을 보내보세요.
http://127.0.0.1:8000/items/42
위 URL로 요청을 보내면 다음과 같은 JSON 형태의 응답이 출력됩니다.
{"item_id": 42}
경로 매개변수는 int, float, bool, UUID 등 다양한 형식으로 지정할 수 있습니다. 또한, 경로 매개변수 뒤에 /:variable_name 형식으로 쿼리 매개변수를 추가할 수도 있습니다. 쿼리 매개변수는 선택적 매개변수로, 기본값을 지정할 수 있습니다.
Request Body 처리하기
FastAPI는 JSON 형식의 요청 데이터를 쉽게 처리할 수 있습니다. 다음과 같은 코드를 작성해보세요.
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
is_offer: bool = None
app = FastAPI()
@app.post("/items/")
def create_item(item: Item):
return item
위 코드에서 Item 클래스는 요청으로 받을 JSON 데이터의 형식을 정의합니다. create_item() 함수는 POST 요청을 받아서 Item 형식의 데이터를 파싱한 후 반환합니다.
요청을 보내기 위해서는 HTTP 클라이언트를 사용하거나, curl 명령어를 이용할 수 있습니다. curl 명령어를 이용하여 요청을 보내보겠습니다.
curl -X POST "http://127.0.0.1:8000/items/" \
-H "Content-Type: application/json" \
-d '{"name": "foo", "price": 42.0, "is_offer": true}'
위 명령어는 다음과 같은 JSON 데이터를 요청 본문에 담아서 서버로 보냅니다.
{"name": "foo", "price": 42.0, "is_offer": true}
서버는 요청을 받아서 다음과 같은 JSON 응답을 반환합니다.
{"name": "foo", "price": 42.0, "is_offer": true}
응답 모델 지정하기
FastAPI는 응답으로 반환될 데이터의 형식도 명시할 수 있습니다. 다음과 같은 코드를 작성해보세요.
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
is_offer: bool = None
class ItemOut(BaseModel):
name: str
price: float
tax: float = None
app = FastAPI()
@app.post("/items/", response_model=ItemOut)
def create_item(item: Item):
return {"name": item.name, "price": item.price, "tax": item.price * 0.1}
위 코드에서 ItemOut 클래스는 반환될 JSON 데이터의 형식을 정의합니다. create_item() 함수는 Item 형식의 요청 데이터를 처리한 후, ItemOut 형식으로 변환하여 반환합니다.
서버를 실행한 후 요청을 보내보면 다음과 같은 JSON 응답이 반환됩니다.
{"name": "foo", "price": 42.0, "tax": 4.2}
응답 상태 코드 지정하기
FastAPI는 응답 상태 코드도 명시할 수 있습니다. 다음과 같은 코드를 작성해보세요.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
is_offer: bool = None
class ItemOut(BaseModel):
name: str
price: float
tax: float = None
app = FastAPI()
@app.post("/items/", response_model=ItemOut, status_code=201)
def create_item(item: Item):
return {"name": item.name, "price": item.price, "tax": item.price * 0.1}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
if item_id == 42:
raise HTTPException(status_code=418, detail="I'm a teapot")
return {"item_id": item_id, "q": q}
위 코드에서 create_item() 함수에는 status_code=201 인자를 추가하여, 성공적으로 생성되었을 때 반환할 응답 상태 코드를 201로 지정합니다. read_item() 함수에서는 HTTPException 예외를 발생시켜 418 상태 코드와 함께 메시지를 반환합니다.
미들웨어 사용하기
FastAPI는 미들웨어를 사용하여 요청과 응답을 처리할 수 있습니다. 미들웨어는 다음과 같은 코드로 등록할 수 있습니다.
from fastapi import FastAPI, Request
app = FastAPI()
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
import time
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
위 코드에서 add_process_time_header() 함수는 미들웨어로 등록됩니다. 이 함수는 요청이 들어올 때마다 시작 시간을 기록하고, call_next() 함수를 호출하여 요청을 처리합니다. 그 후에는 처리 시간을 계산하여 응답 헤더에 X-Process-Time이라는 이름으로 추가하고, 응답을 반환합니다.
이제 서버를 실행하고 요청을 보내보면 응답 헤더에 X-Process-Time이 추가된 것을 확인할 수 있습니다.
$ curl -i http://127.0.0.1:8000/items/42?q=test
HTTP/1.1 200 OK
date: Fri, 19 Mar 2021 14:12:05 GMT
server: uvicorn
content-length: 19
content-type: application/json
x-process-time: 0.000133991
{"item_id":42,"q":"test"}
정리
FastAPI는 빠른 속도와 간편한 사용성, 자동 문서화와 같은 기능을 제공하여 웹 애플리케이션 개발을 쉽게 만들어줍니다. 또한 Pydantic을 사용하여 타입 힌트를 이용한 데이터 유효성 검사를 지원하므로 개발자의 실수를 사전에 방지할 수 있습니다.
이 글에서는 FastAPI의 기본적인 기능과 사용 방법을 간단하게 살펴보았습니다. FastAPI는 다양한 기능과 확장성을 제공하기 때문에, 이 글을 참고하여 더욱 심화된 FastAPI 웹 애플리케이션 개발을 진행하실 수 있을 것입니다.