반응형

Fast API 기본 구조

Fast API를 통해 웹을 구축할 때 기본적인 구조는 아래 코드와 같이 구축하면 됩니다. 기본적으로 FastAPI를 불러오고, 관련된 코드를 작성합니다.

from fastapi import FastAPI
import uvicorn

app = FastAPI()

##### Code ######
@app.get("/")
def read_root():
    return {"Hello": "World"}
##### Code ######

if __name__ == '__main__':
    uvicorn.run(app, host="0.0.0.0", port=8000)

그리고 uvicorn을 통해 파이썬 파일을 실행시킵니다. uvicorn은 Asynchronous Server Gateway Interface(ASGI)라 불리는 비동기 코드를 처리할 수 있는 파이썬 웹 서버인 프레임워크 간 표준 인터페이스 입니다. 실행하는 방법은 아래와 같이 CLI 입력하면 됩니다. 만약 아래처럼 입력하지 않고 코드 하단에 uvicorn.run을 추가하면 됩니다.

$uvicorn [.py 확장자 없는 파일명]:app --reload

Path Parameter

패스 파라미터를 구현하기 위해서는 코드 부분에 아래 내용을 추가하면 됩니다.

@app.get("/users/{user_id}")
def get_user(user_id):
    return {"user_id": user_id}

Query Parameter

쿼리 파라미터를 구현하기 위해서는 코드 부분에 아래 내용을 추가하면 됩니다.

test_db = [
    {
        'item_name' : "Foo"
    },
    {
        'item_name' : "Bar"
    }
]

@app.get("/items/")
def read_item(skip:int = 0, limit: int = 10):
    return test_db[skip:skip+limit]

앞서 언급한 패스 파라미터와 쿼리 파라미터에 대한 간단한 내용은 아래에서 살펴볼 수 있습니다.

[온라인 서빙을 위한 웹에 대한 기본 지식 정리 | REST API

온라인 서빙고려사항온라인 서빙은 실시간으로 클라이언트 요청에 대한 서비스를 제공해야 하는 구조 입니다. 따라서 고객 경험을 좋게 하기 위해서는 지연 시간(Latency)를 최소화할 필요가 있

seanpark11.tistory.com](https://seanpark11.tistory.com/173#url-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0)

Optional Parameter

특정 파라미터에 대해서 선택적으로 하고 싶은 경우 아래 코드와 같이 구현할 수 있습니다. 아래 코드에서는 q가 있냐 없느냐에 따라 다르게 반환합니다. 이를 구현하기 위해선 typing 라이브러리의 Optional을 활용합니다.

from typing import Optional 

@app.get("/items/{item_id}")
def read_item(item_id:str, q: Optional[str]=None):
    if q:
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id}

Request Body

클라이언트에서 API에 데이터를 보낼 때 사용하는 Payload로 데이터를 보내고 싶다면, POST 메서드를 사용합니다. 아래 예제는 Request Body에 타입 힌트를 생성한 클래스를 상속받아 데이터를 검증할 수 있도록 했습니다.

from typing import Optional
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


@app.post("/items/")
def create_item(item: Item):
    return item

Schemas에서 정의한 내용을 살펴봤습니다. 정의된 것처럼 잘 나오는 것을 확인할 수 있습니다.

Response Body

Response Body는 Request Body의 반대로 API의 응답이 클라이언트에게로 전달되는 것입니다. 아래 코드는 입력되는 값(ItemIn)에 대해 응답하는 값(ItemOut)을 POST 메서드를 적용합니다.

class ItemIn(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


class ItemOut(BaseModel):
    name: str
    price: float
    tax: Optional[float] = None


@app.post("/items/", response_model=ItemOut)
def create_item(item: ItemIn):
    return item

Form

구글 폼과 같이 데이터를 입력받기 위해 Form 클래스를 사용하면, 요청하는 형식의 함수인 Request의 데이터를 가져올 수 있습니다. GET을 통해 해당 페이지를 조회하고 입력받은 데이터를 보내는 POST 메서드를 각각 구현합니다.

또한, 프론트의 구현을 위해 Jinja2를 활용했는데 템플릿을 활용해 로그인 폼을 구현합니다. Jinja2Templates에서는 {{}}에 들어있는 데이터를 사용할 수 있게 됩니다. (여기서는 login_form.html은 있다고 가정) 추가적으로 덧붙인다면, 아래와 같은 코드 구현을 위해서는 사전에 Jinja2와 python-multipart 설치가 필요합니다.

from fastapi import Form, Request
from fastapi.templating import Jinja2Templates


template = Jinja2Templates(directory='./')

@app.get("/login/")
def get_login_form(request: Request):
    return template.TemplateResponse('login_form.html', context={'request': request})

@app.post("/login/")
def login(username: str = Form(...), password: str = Form(...)):
    return {"username" : username}

File

파일을 업로드하고 싶다면 File과 UploadFile을 이용할 수 있습니다. main 함수에서는 입력받을 수 있는 요소를 넣기 위해 HTML을 입력해 HTMLResponse를 통해 구현했습니다. 그리고 파일을 업로드하면 각각 사이즈와 파일명을 반환할 수 있는 함수들입니다.

from typing import List
from fastapi import File, UploadFile
from fastapi.responses import HTMLResponse


@app.post("/files/")
def create_files(files: List[bytes] = File(...)):
    return {"file_sizes": [len(file) for file in files]}

@app.post("/uploadfiles/")
def create_upload_files(files: List[UploadFile] = File(...)):
    return {"filename": [file.filename for file in files]}

@app.get("/")
def main():
    content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
    """
    return HTMLResponse(content=content)

참고자료

[1] 변성윤. "[Product Serving] Fast API (1)". boostcamp AI Tech.

반응형