본문 바로가기

개발 Note/NginX+FastAPI

[NginX+Fast API] 2. REST API 설계

반응형

Fast API 사용을 위한 서버 구축을 완료 했다면, 이제 서비스 구현을 해 나가야 겠죠?

가장 필요한것은 API들을 만들어 나가는 것인데요.

Web에서 현재 거의 표준이다시피 한 것이 REST API 일 것입니다.

REST API 를 Restfull 하게 설계 하기 위해서는 몇가지 알아 두어야 할 사항이 있습니다.

REST API 설계 레시피

 

1. CRUD - POST/GET/PUT/DELETE 에 맞춰서 설계한다.

2. RESOURE 정의 데이타 중심으로 한다.

 - api에 동사 사용하지 않는다 : http://server.com/get-items => GET http://server.com/items 

 - 소문자만 사용한다 : GET http://server.com/Items => GET http://server.com/items 

 - 단어와 단어 사이에는 "_"(underscore, 밑줄) 대신 "-"(dash, 중간선)을 사용한다. 

  GET http://server.com/shoping_items => GET http://server.com/shoping-items  

 

먼저 HTTP 의 request 종류와 용도를 알아두면 좋습니다.

 

 

HTTP request 와 CRUD

아마 REST API를 검색하면 많은 빈도수로 CRUD가 나올 것입니다.

 

  REST API example  (resource = item)
http://myserver.com/api/item
C
Create
POST
item 생성
POST http://myserver.com/api/item/12223 

  name:"hello",
  value:"1234"
}
R
Read
GET
item 읽기
GET http://myserver.com/api/item/12223 

U
Update
PUT/ PATCH
item 업데이트
PUT http://myserver.com/api/item/12223 

  name:"hello",
  value:"1234"
}
PATCH  http://myserver.com/api/item/12223 

  value:"1234"
}
D
Delete
DELETE
item 삭제
DELETE http://myserver.com/api/item/12223 

 

 

원래 DB 쪽에서 시작된 용어이긴 하지만 일반적인 API 설계시에도 잘 들어 맞습니다.

그래서 REST API 설계시에도 매우 유용한 개념이기 때문에 REST API 설계시 사용하기 시작했습니다.

 

 

 

Fast API로 REST API 설계하기

 

Fast API로 rest api의 형태를 잡기 위해서는 가장 먼저 알아놔야 할것이  rest api 파라미터(parameter)의 형태를 어떻게 가져갈 것인가 입니다.

 

경로 파라미터

url 기본 패스(path)로 정의 하는 형태입니다.

아래와 같이 items 가 api의 resource에 해당하는 파트입니다. 즉, items 에 접근하기 위한 api를 의미합니다. 따로 get-items 와 같이 동사를 붙이지 않죠. GET이라는 행위는 http request의 형식에 GET으로 정의 합니다.

 

GET http://myserver.com/items

 

Fast API로는 아래와 같이 구현 합니다.

from fastapi import FastAPI

app = FastAPI()


@app.get("/items")
async def get_item_counts():
    return {"count": 10}

Fast API로 api를 정의한 부분을 보니 , 간단하고 보기 편하죠?

 

그다음 좀더 확장해서 경로 파라메터에 변수를 포함해서  활용하는 방법입니다. 

패스에 변수를 포함시키는 형태는 이와 같습니다.

GET http://myserver.com/items/{item_id}

ex) GET http://myserver.com/items/10

items/10 은 여기서 10번 item 정보를 가져온다고 가정 하죠.

이를 fast API에서는 아래와 같이 표현합니다.

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id):
    return {"item_id": item_id}

read_item() 이라는 함수에 item_id를 넣고, item_id를 입력받은 변수로 사용하면 됩니다.
실제 구현에서는 item_id에 해당 하는 item을 꺼내서 return 해주면 되겠죠?

 

아래의 user_id 처럼 주소 중간에도 추가가 가능합니다.

@app.get("/users/{user_id}items/{item_id}")
async def read_user_item(user_id, item_id):
    return {
    "user_id": user_id,
    "item_id": item_id
    }

 

형태를 봤을때 경로 파라메터는 아주 단순하죠? 좀더 복잡하고 다양한 형태의 입력을 받아야 하는 경우들이 인터넷 세상에는 많습니다.

 

복잡하고 많은 정보를 입력으로 받아야 하는 경우, 2가지 형태로 구현할 수 있습니다.

첫번째는 쿼리(URL query) 형태입니다.

 

쿼리(Query)

쿼리 형태는 사실 표현 형식에서 경로 형태에 파라메터가 추가되는 형태로 흔히 브라우져에서 주소 입력창에서 자주 보던 형태 일건데요.

아래와 같은 형식입니다.

POST http://myserver.com/items ?user_id="goodboy" & item_id="123"

 

이렇게 ? 뒤에 key-value 형태로 파라메터를 추가해서 전달하는 방식입니다.

python 함수 내에 parameter로 정의 하는 것 만으로도 쿼리 구현이 됩니다. (fast api에 잘 구현되어있어서 편하게 쓸수 있네요.)

@app.post("/items")
async def add_item(user_id:str, item_id:str):
    return {
        "result":"success",
        "item_id":"D1234-889X-XX",
        "price":"5000000",
    }

 

데이타의 형태가 복잡해지거나 로직이 복잡해질 수록 query 처리하기 힘들어 지는 경우들이 발생합니다.

그중 한가지 예로 클래스로 데이타를 묶고 클래스로 데이타를 전달받고 처리하면 편리해질 것입니다.

이때 클래스의 구조가 바뀌면 parameter 형태도 바뀌게 되서 찾아서 수정해야 할 부분도 많아지겠죠.

이런 불편을 덜 수 있는 형태가 Requst body 입니다.

 

Request Body

Requst body를 이용하면 클래스와 같은 데이타 묶음을 처리하기 쉽습니다.

 

코드 를 작성할때 아래와 같이 어떤  정보를 json 으로 다뤄야 할 경우, 다음과 같이 합니다.

fast api에서 이렇게 class 를 json object로 잘 다룰 수 있도록 Pydantic BaseModel 이 구현되어 있습니다.

 

Pydantic BaseModel

먼저 Pydantic모듈의 BaseModel을 import하여 Class를 구성한다.

 

from typing import Union, List, Optional
from fastapi import FastAPI, Query
from pydantic import BaseModel


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


@app.post("/items/{item_id}")
async def add_tree(item:Item):
    pick = itemTable[item]
    return {
        "result":"success",
        "item_name":pick.name,
        "price":pick.price,
    }

이렇게 Item이 모듈화 됨으로 해서 구현이나 관리가 훨씬 편리해지고 유연해 질 수 있습니다.

 

 

이정도를 기초로 익혀두면 자신의 서비스를 확장해 나가는데 도움이 될것 같습니다.

더 심오한 내용이나 복잡한 것들은 추가로 Fast API 사이트를 레퍼런스 삼아서 공부 해야 겠죠 ^^

 

1. NginX 와 Fast API 셋업은 여기를...

 

해피 코딩 ^^!!

 

 

참고자료.

https://juna-dev.tistory.com/7

 

06. Fast API, Request Body (POST, PUT) 받기

지금까지는 GET방식이기에 URL 및 Request Header로 값이 넘어왔다. 하지만 POST방식에서는 Request Body로 넘어오기에 이전가지의 방식으로는 데이터를 받을 수 없다. Request Body는 Pydantic Model을 이용하여

juna-dev.tistory.com

 

Fast API 튜토리얼

https://fastapi.tiangolo.com/ko/tutorial/

 

자습서 - 사용자 안내서 - 도입부 - FastAPI

자습서 - 사용자 안내서 - 도입부 이 자습서는 FastAPI의 대부분의 기능을 단계별로 사용하는 방법을 보여줍니다. 각 섹션은 이전 섹션을 기반해서 점진적으로 만들어 졌지만, 주제에 따라 다르게

fastapi.tiangolo.com