포스트

vscode에서 편리한 postman 사용하기 with FastAPI

api를 테스트하는 방법은 매우 여러가지가 있습니다. 그 중에서는 아주 유명한 postman을 사용하는 방법이 있죠.

그런데 그걸 vscode의 확장프로그램으로 설치해서 사용하면 더 편리합니다.

심지어 .env에서 자동으로 환경변수를 가져와주고 동기화해주는 기능도 있습니다.

fastapi로 예제 api를 만들어 테스트해보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
## main.py
from typing import Union

from fastapi import FastAPI
from fastapi import Request

app = FastAPI()


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


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


@app.get("/get_sentiment/{text}")
def get_sentiment(text: str, user_id: Union[str, None] = None):
    return {"text": text, "sentiment": "positive", "user_id": user_id}


@app.get("/get_sentiment_v2/{text}/{ip}")
def get_sentiment_v2(text: str, ip: str, user_id: Union[str, None] = None):
    return {"ip": ip, "text": text, "sentiment": "positive", "user_id": user_id}


@app.post("/get_twitter_sentiment")
def get_twitter_sentiment(text: str, ip: str, user_id: Union[str, None] = None):
    return {"ip": ip, "text": text, "sentiment": "normal", "user_id": user_id}


@app.post("/get_twitter_sentiment_v2")
async def get_twitter_sentiment_v2(request: Request):
    data = await request.json()

    text: str = data.get("text")
    ip = data.get("ip")
    user_id = data.get("user_id")

    return {"ip": ip, "text": text, "sentiment": "normal", "user_id": user_id}

python -m uvicorn main:app –reload

로 서버를 실행해준 다음, postman에서 get과 parameter post, 그리고 body post를 테스트해봅시다.

  1. get 테스트

get요청을 보내는 get_sentiment_v2 api를 보시면 text, ip는 필수 입력이고 user_id는 선택 매개변수입니다. 필수는 “/” 뒤에 나와야 하고 선택 매개변수는 “?” 뒤에 나오면 됩니다. 그대로 입력하게 되면 다음과 같습니다.

  1. post 테스트

post 요청을 보내는 get_twitter_sentiment 요청과 get_twitter_sentiment_v2 요청은 그 보내는 방식이 get 요청과도 다르고, 서로간에도 조금 다릅니다. 전자는 url에 매개변수를 넣어서 보내고, 후자는 data payload에 전부 매개변수를 넣어서 보냅니다.

그럼 전자부터 볼까요?

get_twitter_sentiment post 요청은 url에 모든 매개변수를 넣어서 보냅니다. 이러면 아까 했던 get요청과 뭐가 다를까요? get 요청도 url에 모든 매개변수를 넣어서 보냈었습니다.

1
2
3
4
5
6
7
8
@app.get("/get_sentiment_v2/{text}/{ip}")
def get_sentiment_v2(text: str, ip: str, user_id: Union[str, None] = None):
    return {"ip": ip, "text": text, "sentiment": "positive", "user_id": user_id}


@app.post("/get_twitter_sentiment")
def get_twitter_sentiment(text: str, ip: str, user_id: Union[str, None] = None):
    return {"ip": ip, "text": text, "sentiment": "normal", "user_id": user_id}

다른 점은, “/”와 “?”를 모두 사용했던 get과는 달리 post의 url에서는 필수 변수라 하더라도 경로 “/”로 들어가지 않는다는 점입니다. 모두 선택 매개변수 “?”로 들어갑니다.

이제 전자와 후자를 비교하겠습니다.

전자는 매개변수를 url에 다 넣는 것이고, 후자는 data payload에 매개변수를 넣어서 보냅니다. data payload는 다른 용어로 body입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@app.post("/get_twitter_sentiment")
def get_twitter_sentiment(text: str, ip: str, user_id: Union[str, None] = None):
    return {"ip": ip, "text": text, "sentiment": "normal", "user_id": user_id}


@app.post("/get_twitter_sentiment_v2")
async def get_twitter_sentiment_v2(request: Request):
    data = await request.json()

    text: str = data.get("text")
    ip = data.get("ip")
    user_id = data.get("user_id")

    return {"ip": ip, "text": text, "sentiment": "normal", "user_id": user_id}

Request 라는 타입은 from fastapi import Request 입니다.

get_twitter_sentiment_v2 post 요청을 보내보겠습니다.

캡처와 같이 request의 body 안에 넣을 json을 완성해서 send 하겠습니다.

data payload방식과 url에 방식에는 또 다른 차이점이 있습니다.

data payload에는 필수 매개변수를 넣지 않아도 응답이 돌아옵니다.

왜냐하면 모두 선택 매개변수로 취급되기 때문인데요,

그래서 실제 프로덕션으로 내보냈을 때 이런 경우가 문제가 될 수 있다고 합니다.

필수 매개변수를 안 보냈으면 잘못됐다고 알아차릴 만한 장치가 여긴 없으니까요.

그래서 반드시 request로 보내기 전에 필수 입력되어야 하는 값은 없는지 체크를 철저히 해야 합니다.

python의 경우에는 pydantic을 사용해서 철저하게 타입을 체크해주게 됩니다. 여기서는 다루지 않겠습니다.

  1. 사용한 API 저장

save를 누르면 사용했던 api 요청을 나중에 다시 쓸 수 있도록 저장해둘 수도 있습니다.

  1. FastAPI 라면 SwaggerUI로 더 쉽게

사실 fastapi라면 왠만하면 swaggerUI로 쉽게 테스트할 수 있습니다.

다만 vscode의 postman extension을 사용하는 경우는 로컬에서 자주 사용하는 api 테스트 매개변수를 저장해두고 사용할 수 있다는 점이 편리한 점이죠.

그러니 병행해서 사용하면 좋겠습니다.

sticker

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.