[Python] Flask 대안으로 FastAPI Develop Tip

이번에 페친님의 어느 소개 페이지로 
"11 new Python web frameworks" 라는 사이트를 보았습니다.

 1. Sanic
 2. Starlette
 3. Masonite
 4. FastAPI
 5. Responder
 6. Molten
 7. Japronto
 8. Klein
 9. Quart
11. Cyclone

위와 같은 웹 프레임워크를 소개하고 있었습니다.

봐 내려가는 동안 uvloop 와 파이썬 3.x의 asyncio 를 이용한 속도 개선이 큰 방향이었고,
역시나 비동기 WSGI 라 할 수 있은 ASGI 를 이용한 것들이 대부분이라 할 수 있었습니다.

그 중에서도 라이센스, 도움말, 좋아하는 정도 등을 가볍게 훑어본 결과
FastCGI 가 가장 마음에 들어 살펴보게 되었습니다.
(실은 2 Starlette 위에 편리한 기능을 더해서 만들었다는...)

그동안 속도 때문에 GO 언어로 가야 되나 하고 생각하고 있었던 파이썬 웹 API 등을
이 FastAPI 를 이용하면 거의 GO 정도의 성능이 나온다고 하니..
'앗싸! 파이썬으로 이런 성능 향상이..?' 하는 것은 덤으로..
더 훌륭한 기능 등이 많았습니다.

3년 전 쯤 JSON 스키마 및 파이썬에서의 고찰을 살펴보기도 했습니다만,
더 개선된 방식으로 FastAPI 에서는 Pydantic과 OpenAPI(Swagger에서 이름에 바뀌었나 봅니다)를
이용하여 문서및 테스트가 아주 쉽게 가능합니다.

우선 설치 모듈은,

pip install fastapi uvicorn

명령으로 두 개의 모듈을 pip 로 설치하면 됩니다.

자세한 것은 차후 Flask 대신 운영을 하면서 시행착오를 기술해 보겠고,
이번에는 다음과 같은 테스트를 진행했습니다.

venv 환경에서 위의 두 모듈을 설치했고,
main.py 라는 파일에 다음의 내용을 넣고,

from fastapi import FastAPI, Query
from pydantic import BaseModel


################################################################################
app = FastAPI()


################################################################################
class User(BaseModel):
    id: int
    name: str
    email: str


################################################################################
async def update_user(*, user: User):
    pass


################################################################################
async def get_user(*, user_id: int):
    u = User()
    u.id = user_id
    u.name = 'my name %d' % user_id
    u.email = 'my%d@a.b.c' % user_id
    return u


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


################################################################################
@app.get('/user', response_model=User)
async def user(
    *,
    user_id: int = Query(..., title="The ID of the user to get", gt=0)
):
    # return {'user_id': user_id}
    my_user = get_user(user_id=user_id)
    return my_user


################################################################################
@app.post('/user/update', response_model=User)
async def update_user(
    *,
    user_id: int,
    really_update: int = Query(...)
):
    pass

위와 같이 코드를 작성하면 됩니다.
Flask와 비교해도 거의 유사하지만, 몇 가지 asyncio 및
3.6 이후의 최신 파이썬 문법에 따라 약간 다른 점이 있습니다.

코드를 읽다가 몇가지 것을 정리해 봅니다.

우선 다음과 같이,

async def update_user(*, user: User)
함수 정의 시, * 라는 것이 처음 또는 중간에 나올 수 있습니다.

기존에는 *args 라는 것으로 이용했을 경우는 있었어도,
단일 * 는 처음 봐서 이것이 무엇이지 하고 찾아보았더니,

단일 * 이 나온 다음 부터는 꼭 keyword 패러미터가 나온다는 것을
명시한다 합니다.

(a, b, *, k1=v1, k2=v2) 는 가능해도,
(a, b, k1=v1, *, k2=v2) 는 오류가 발생하는 것이었습니다.

Query(..., title="The ID of the user to get", gt=0)
또한 위와 같이 ... 라고 사용하는 경우도 있는데,
이것은 Elipse 객체로써 다음 두 가지 의미를 지닐 수 있습니다.

하나는 nop 라는 것으로,

def todo_func():
    ...

라고 기술할 수 있습니다.
(pass 라고 했었는데, 이렇게 하니 더 직관적이네요)

또 하나는 tuple에서의 ... 을 넣어주면, 가변 길이의 Tuple을 의미한다 합니다.

함수의 패러미터도 결국은 튜플로 표현되는데,

Query(..., title="The ID of the user to get", gt=0)
에서 ... 라고 나온 것은 이전에 사용자가 지정한 것 이외에 지정하는 것으로,
의미론 적으로 표현되는 것 같습니다.
(혹시 다른 의미를 아신다면 알려주십시오)

위와 같은 것을 돌리는 것은 AWGI 구현체 중에 하나인,
uvicorn (처음에는 unicorn 오타인줄 .. T.T)으로 다음과 같이 돌리면 됩니다.

uvicorn main:app --reload

그러면,

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [92526]
INFO:     email-validator not installed, email fields will be treated as str.
To install, run: pip install email-validator
INFO:     Started server process [92539]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

와 같은 식으로 로그가 보입니다.

제일 먼저 http://127.0.0.1:8000 으로 접속해 보면,

와 같이 ('/') 지정한 결과 JSON이 보입니다.

이제 재미난 것은 알아서 API swagger 및 문서 등이 만들어 진다는 것입니다.

http://localhost:8000/docs 를 접속하면 위와 같이 swagger 같은 화면이 나타나고,


직접 쉽게 값을 넣고 결과를 실행해 볼 수 있습니다.

그리고 http://localhost:8000/redoc 를 접속하면 알아서 API 문서가 만들어 집니다.
이것은 예전에 Flask에 swagger ui를 붙이려고 했던 것에 비하여 비약적으로 편해졌습니다.

또한 Flask에서는 큰 프로젝트를 만들려면 Blueprint 라는 개념을 이용했는데,
FaskAPI에서는 API Router 라는 개념으로 파이썬 패키지 만들듯이
쉽게 만들 수 있는 장점이 있습니다.

속도도 빠르고 Flask 사용하면서 불편했던 점들이 아주 쉽게 사용가능하고,
이제 OAuth 등등 기존 Flask에 여러 Add-in 모듈들이 확장되면
아주 강력해질 것 같다는 생각이 듭니다.

 
어느 분께는 도움이 되셨기를 ..

덧글

댓글 입력 영역

구글애드텍스트