설치
pip install fastapi
fastapi의 설치는 간단합니다. 위와 같이, pip를 통해 간단하게 설치합니다.
pip install uvicorn
fastapi를 사용하기 위해서는 추가로, 서버역할을 하는 uvicorn을 설치해야합니다.
기본예제
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
docs를 보면 나오는 가장 간단한 FastAPI코드입니다. 해당 코드를 main.py
에 작성하고, 서버를 실행해봅시다.
uvicorn main:app --reload
위의 코드로 서버를 실행할 수 있습니다.
이전에 설치한 uvicorn을 이용해서 서버를 실행합니다. main:app의 의미는 main이라는 파이썬 파일에서 app = FastAPI()줄에서 생ㅅ어한 오브젝트를 실행한다는 뜻입니다.
--reload
는 변경사항이 있을 때, 재로드 한다는 뜻입니다. 개발할 때 참 편리한 기능입니다.
http://127.0.0.1:8000
http://127.0.0.1:8000/docs
http://127.0.0.1:8000/redoc
http://127.0.0.1:8000/openapi.json
FastAPI는 상당히 많은 도구를 지원해 줍니다. 하나씩 확인해보세요.
경로 동작 데코레이터 정의
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
위의 코드의 데코레이터를 보면, 경로가 ‘/’ 로 되어 있습니다.
@app.get("/hello")
async def root():
return {"message": "Hello World- this is hello"}
만약 위와 같이 경로가 ‘/hello’로 설정되어 있다면, http://127.0.0.1:8000/hello 경로는 hello가 됩니다.
동작
여기서 “동작(Operation)”은 HTTP “메소드” 중 하나를 나타냅니다.
다음 중 하나이며:
POST
GET
PUT
DELETE
…이국적인 것들도 있습니다:
OPTIONS
HEAD
PATCH
TRACE
HTTP 프로토콜에서는 이러한 “메소드”를 하나(또는 이상) 사용하여 각 경로와 통신할 수 있습니다.
FastAPI Docs를 보면 위와같이, 기본적인 동작 이외 이국적인 것 까지 할 수 있습니다.
async def vs def
@app.get("/")
async def root():
return {"message": "Hello World"}
@app.get("/")
def root():
return {"message": "Hello World"}
async def와 def가 있는데, async의 경우 응답을 대기하지 않을 때 사용합니다.
async를 사용하면 기본 def보다 좋은 성능을 보여줍니다. 이것이 FastAPI의 장점입니다.
return
Return의 경우, 파이썬답게 딕셔너리를 사용해서 반환합니다.
매개변수 사용하기
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}
위와 같이. {item_id} 처럼 매개변수를 인자로 받고 사용할 수 있습니다.
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
위와같이, int 등의 자료형을 설정하여 사용할 수 있습니다.
저는 플라스크랑 장고를 해본적 있어서 위와같이 사용하는 것이 익숙하네요.
순서문제
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/me")
async def read_user_me():
return {"user_id": "the current user"}
@app.get("/users/{user_id}")
async def read_user(user_id: str):
return {"user_id": user_id}
FastAPI는 순서의 문제가 있는데, 위에있는 코드가 우선권을 가지게 됩니다.
즉, http://127.0.0.1:8000/users/me 로 접속할 경우, return 값은, {‘user_id’: “the current user”} 이 됩니다.
Enum 사용하기
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
위와 같이, Enum을 정의하고 클래스를 통해 고정형 값을 사용할 수 있습니다.
이때 http://localhost:8000/docs 로 접속했을 때, FastAPI의 강점을 알겠더라구요. Available values 를 표기해줘서 테스트하기 좋게 구성되어 있습니다.
디폴트값 주기
from fastapi import FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
return fake_items_db[skip : skip + limit]
위의 코드와 같이, 디폴트 값을 줄 수 있습니다. 위의 경우 skip이라는 변수에 int=0, limit라는 변수에 int=10이 들어갑니다.
Post
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
이전까지 get 요청을 사용했다면, 이번에는 post 요청입니다. Post요청은 위와 같이, 클래스를 선언해서 사용합니다.
Query
from typing import Optional
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Optional[str] = Query(None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
쿼리할 때, 조건을 추가할 수 있는데, 위와같이, Query함수를 사용해서 max_length=50 으로 설정할 수 있습니다.
이외에도, min, 정규표현식, 또는 기본값 설정 등 다양한 조건을 추가할 수 있습니다.