Fast API 활용 1

DONGJIN IM·2022년 7월 12일
0

Product Serving 이론

목록 보기
8/10

Fast API 활용

Base 활용

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello":"World"}
  • Fast API를 통해 백엔드 실행 : uvicorn streamlit_example:app

    • uvicorn : 명령어
    • streamlit_example : 실행시킬 Python 파일 이름
    • app : FastAPI() 객체 이름
      • 위 코드에서 app=FastAPI()를 통해 FastAPI 객체를 만들었으므로 app을 입력한 것이다. 이렇듯 Fast API를 활용하는 백엔드를 개발하기 위해서는 FastAPI 객체를 활용한다는 것을 명령어에도 포함시켜야 한다.
  • http://127.0.0.1:8000/ 으로 가면 내가 원하는 웹 메인 페이지로 접속할 수 있다

    • 위에서는 "/"가 root를 의미하고, return을 통해 값을 반환하므로 이 값에 대한 출력이 뜰 것이다

명령어 uvicorn 활용하지 않기

  • 명령어를 수행할 때마다 uvicorn ~:app을 수행하기엔 귀찮을 수 있다. 이럴 때 python으로 수행시키고 싶을 수도 있는데, 여기에도 방법이 존재한다
from fastapi import FastAPI
import uvicorn

app = FastAPI()

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

if __name__=='__main__':
    uvicorn.run(app, host='0.0.0.0', port = 8000)
  • 실행 명령 : python streamlit_example.py
    • FastAPI 객체를 입력하지 않아도 됨
    • python의 uvicorn.run에서 알아서 처리해줌(인자로 전달해줌)
  • 나중에 Router를 전달할 때도 위 방법이 편한 것 같기 때문에 이 방법 추천

Swagger

  • 'locahost:8000/docs'로 이동하면 Swagger 확인 가능
    • Request를 보냈을 때 응답 코드 및 데이터를 보여줌
    • 'Try it out' 버튼을 클릭하여 Request를 보낼 수 있음

  • 'localhost:8000/redoc'으로 이동하면, 웹 사이트에 대한 Document 문서를 자동으로 만들어 줌

Path Parameter

  • 데코레이터(@app.get, @app.post)를 통해 GET, POST 표시
from fastapi import FastAPI
import uvicorn

app = FastAPI()

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

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

Query Parameter

from fastapi import FastAPI
import uvicorn

app = FastAPI()

fake_db = ['A','B','C','D']

@app.get("/items")
def read_root(start:int=0,end:int=5):
    return fake_db[start:end]

if __name__=='__main__':
    uvicorn.run(app, host='0.0.0.0', port = 8000)
  • fake_db에서 start ~ end까지의 List 값을 반환하는 메서드

  • &를 통해 start, end 값을 연결함
  • 만약 아무런 데이터도 전달하지 않는다면, start:int=0으로써 start는 0으로, end는 5로 설정되어 결과를 반환

Optional Parameter

  • 특정 Parameter는 입력 여부를 선택으로 하고 싶다면, Optional을 활용하면 됨
    • 해당 Parameter가 입력되지 않으면 None으로써 없는 값 취급하고, 입력될 경우에만 해당 데이터를 처리함
  • from typing import Optional로써 import 가능
from fastapi import FastAPI
from typing import Optional
import uvicorn

app = FastAPI()

fake_db = ['A','B','C','D']

@app.get("/items")
def read_root(start:int=0,end:int=5, skip:Optional[int]=None):
    if not skip:
        return fake_db[start:end]
    return fake_db[start:skip] + fake_db[skip+1:end]

if __name__=='__main__':
    uvicorn.run(app, host='0.0.0.0', port = 8000)
  • start ~ end까지의 숫자를 표현하는데, skip으로 들어온 index 값은 뺀 리스트를 반환하는 메서드

  • start = 0, end = 3, skip = 1이므로 0번째, 2번째 Index값만 출력해야 하므로 A와 C가 반환됨
  • skip=1 부분을 없애면 A, B, C 모두 출력됨

Request Body

  • GET은 URI에 정보를 담아 Request를 보냈지만, POST 방식은 Packet(Request Body)에 정보를 담아 Request를 보내야 함

  • pydantic을 활용하여 Request Body 데이터 정의

  • from pydanti import BaseModel을 통해 BaseModel 모듈을 가져오고, BaseModel 모듈을 상속받는 클래스를 생성하여 Request Body 형성 가능

from fastapi import FastAPI
from typing import Optional
from pydantic import BaseModel

import uvicorn

app = FastAPI()

# Request Body를 통해 받을 데이터들
class Item_in(BaseModel):
    name: str
    description: Optional[str] = None
    sex: str
    age: int

@app.post("/items")
def create(item:Item_in):
    return item


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

어라, 왜 수행이 안되지?
...라고 생각했다면 POST와 GET을 잘 이해하지 못한것!
위에서 짠 코드는 "POST" 방식의 통신이다.
즉, 데이터를 Packet의 Body에 담아 /items에 접속해야하는데, 이런 과정 없이 GET 방식으로 접근하려니 에러가 발생하는 것이다.
그렇다면 이럴 경우 어떻게 실험할 수 있을까?
원래는 Postman을 활용하면 되지만, 우리에겐 더 쉬운 방법이 있다.
앞에서 말했듯, Fast API의 장점, Swagger!

  • 'localhost:8000/docs'를 통해 들어가면, POST Method의 사이트에 대한 실험이 가능하다. 'Try it out'버튼을 클릭하면 아래처럼 Request Body에 내가 원하는 값을 입력할 수 있다

  • 제대로 된 Response가 올 수 있음을 알 수 있음

Response Body

Request로 데이터가 왔을 때, 대부분의 경우 Respond로 내보내고 싶은 데이터의 형식은 Request 데이터 형식과 다르다.
하지만, @app.post()를 활용하면 Request Body와 동일한 형식의 데이터만 내보낼 수 있게 된다.
즉, "Request Body"와 다른 형태의 데이터 형식을 Respond로 보내고 싶을 때 활용하는 것이 Response Body이다.

  • response_model Parameter 활용
from fastapi import FastAPI
from pydantic import BaseModel

import uvicorn

app = FastAPI()

# Request Body
class ItemIn(BaseModel):
    name:str
    description:str
    sex:str

# Response Body
class ItemOut(BaseModel):
    name: str
    sex: str

# 핵심 구현!!!
@app.post("/items/{item_id}", response_model=ItemOut)
def read_item(inputs: ItemIn):
    item = {'name':inputs.name, 'sex':inputs.sex}
    return item

if __name__=='__main__':
    uvicorn.run(app, host='0.0.0.0', port = 8000)
  • Requesst로 name, description, sex라는 정보가 오면 그 중 name과 sex 정보만 뽑아서 Response로 내보내는 POST 요청을 만들었다

@app.post부분을 보면 response_model=ItemOut을 통해 어떤 객체가 Response Body로써 나갈 것인지 명시해주었다. Request Body는 원래 방식과 동일하다
여기서 중요한 점은 item의 형식이다.
원래 Postman이나 Swagger를 통해 Request를 보낼 때 {"값":"쌍"} 형식(JSON 형식)으로 데이터를 보냄을 알 수 있다.
Respond를 보낼때도 마찬가지이다. JSON 형식으로 Response Body의 Key 값들에 접근하고, Value를 넣어주는 형식으로 데이터를 만들어 이렇게 만든 데이터를 Response Body로 반환해야 한다

  • 참고로 Request Body에서 접근할 때는 '.'을 통해 Key String을 연결하면 Key에 대응되는 Value 값을 얻어올 수 있다
profile
개념부터 확실히!

0개의 댓글