Server의 형태
REST API
REST(Representational State Transfer)의 약자로 자원을 이름으로 구분하여 해당 자원의 상태를 주고받는 모든 것을 의미한다.
1) HTTP URI를 통해 자원을 명시하고, 2) HTTP Method를 통해 해당 자원에 대한 CRUD Operation을 적용하는 것을 의미한다.
웹에서의 통신은 주로 정보를 주고 받을 때 지켜야 하는 통신 프로토콜인 HTTP(Hyper Text Transfer Protocol)를 사용하며 기본적으로 80번 포트를 사용하여 서버와 클라이언트가 통신하게 된다.
URI란?
Uniform Resource Identifier로 인터넷 상의 자원을 식별하기 위한 문자열의 구성
URI는 인터넷 상에서 자원의 위치를 의미하는 URL을 포함하게 되며, URI가 더 포괄적인 범위이다.
CRUD Operation이란?
CRUD는 대부분의 컴퓨터 소프트웨어가 가지는 기본적인 데이터 처리 기능인 Create, Read, Update, Delete를 묶어서 일컫는 말이다.
REST에서의 CRUD Operation 동작은 HTTP Method의 형식으로 표현되는데 Create는 POST, Read는 GET, Update는 PUT, PATCH, Delete은 DELETE이다.
Status Code
클라이언트 요청에 따라 서버가 어떻게 반응하는지를 알려주는 숫자 Code이다.
ex) 404 Not Found, 502 Bad Gate와 같은 에러
Synchronize vs Asynchronize
Fast API의 특징
FastAPI의 장점
FastAPI의 단점
FastAPI 구조 (기초적인 구조)
Poetry를 사용한 Virtual env 관리
자세한 내용은 PDF 참고
Path Parameter vs Query Parameter
Web에서 Get Method를 사용해 데이터를 전송하는 방식은 2가지로 나뉜다.
ex) ID가 402인 사용자 정보를 가져오고 싶은 경우에
Path Paramter in FastAPI
FastAPI는 데코레이터로 Get과 Post를 구분하여 받을 수가 있다.
GET Method의 인자로 있는 {user_id}가 함수의 값으로 주입된다.
from fastapi import FastAPI
import uvicorn
app = FastAPI()
@app.get("users/{user_id}")
def get_user(user_id):
return {"user_id": user_id}
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
Query Parameter in FastAPI
Path Parameter 방식과는 달리 get URL에 Paramter를 넘겨주지 않아도 된다.
하지만, 원하는 Query를 URL뒤에 '?'와 '&'로 연결하여 요청할 수 있다.
또한, 없는 데이터의 경우는 자동적으로 Empty List를 반환해주기 때문에, 추가적인 Error Handling이 필요한 경우도 있다.
from fastapi import FastAPI
import uvicorn
app = FastAPI()
fake_db = [{'item_name': 'Foo'}, {'item_name': 'Bar'}, {'item_name': 'Baz'}]
@app.get("/items/")
def read_item(skip: int=0, limit: int=10):
return fake_db[skip: skip + limit]
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
Optional Parameter
특정 파라미터는 Optional로 선언하고 싶은 경우에는 Typing 모듈의 Optional을 사용하여 지정해준다.
from typing import Optional
from fastapi import FastAPI
import uvicorn
@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}
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
Request Body
클라이언트가 API에 데이터를 보낼 때는 Request Body를 사용하며, 이 때는 POST Method를 사용한다.
GET Method는 Request Header(URL)로 데이터를 전송하고 POST Method는 Request Body로 데이터를 전송하게된다.
from typing import Optional
from fastapi import FastAPI
import uvicorn
from pydantic import BaseModel
class Item(BaseModel):
name:str
description: Optional[str] = None
price: float
tax: Optional[float] = None
app = FastAPI()
@app.post("/items/")
def create_item(item: Item):
return item
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
Response Body
POST Method에 response_model
을 데코레이터에 인자로 Class를 넘겨주면 자동으로 Class에 맞게 Response를 실행하게 된다.
즉, API에서 Client로 전송되는 Output Data를 선언한 Class에 맞게 변형하고, 데이터에 대한 Validation을 진행한 후 Json Format으로 변형하여 Client로 보내주게된다.
아래 코드를 실행할 경우 Request Data는 name, description, price, tax 4가지를 Client에서 API로 요청을 하게되고, API에서 Client로 전송되는 Response Data는 name, price, tax가 응답으로 전송된다.
from typing import Optional
from fastapi import FastAPI
import uvicorn
from pydamic import BaseModel
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 = FastAPI()
@app.post('/items/', response_model=ItemOut)
def create_item(item: ItemIn):
return item
if __name__ == '__main__':
uvicorn.run(app, host='0.0.0.0', port=8000)
Pydantic Library
FastAPI에서 Class를 선언할 때 사용하는 라이브러리로, 요청/응답 시에 Data의 Type이 올바른지 Validation과 Settings을 관리해주는 라이브러리이다.
Type Hinting을 런타임에서 강제하여 안전하게 데이터 핸들링을 처리
파이썬 기본 타입(String, Int 등) + Typing 라이브러리의 List, Dict, Tuple에 대한 Validation 지원
@dataclass
Decorater를 사용하여 설정하게 되면 init을 사용하지 않아도 되고, Validation을 if문을 사용하지 않고 내장 메소드를 사용할 수 있지만, 여전히 Validation을 위한 코드는 필요하다BaseModel
을 상속하고 데이터만 명시해주면 자동으로 init과 Validation을 진행해준다.