API 코딩테스트용으로 fastapi를 사용해본 후 정리하는 글이다.
FastAPI는 현대적이고, 빠르며(고성능), 파이썬 표준 타입 힌트에 기초한 Python3.6+의 API를 빌드하기 위한 웹 프레임워크이다.
FastAPI가 빠른 동작을 보여주는 이유 중 하나는 비동기식 웹 애플리케이션을 사용하기 때문이다.
기존의 WSGI(Web Server Gateway Interface)는 파이썬 웹 애플리케이션과 웹 서버 간의 인터페이스로 사용되었다. 하지만, 동기적인 프로그래밍 모델을 따르기 때문에 동시 처리에 제약이 있었다. Django, Flask같은 프레임워크가 WSGI 기반으로 동기 처리를 지원한다.
ASGI(Asynchronous Server Gateway Interface)는 비동기 웹 애플리케이션을 위한 파이썬 웹 서버와 웹 프레임워크 간의 인터페이스다. 비동기 처리와 동시 처리를 지원하여 더욱 향상된 성능을 보여준다. FastAPI는 ASGI를 기반으로 비동기 처리를 지원한다.
setup.sh
와 같은 라이브러리 설치 파일에 추가한다.
pip install -r requirements.txt
requirements.txt
에 라이브러리와 그 버전 정보를 추가한다.
fastapi==0.68.0
uvicorn==0.15.0
terminal에서 pip list
를 하면 확인할 수 있다.
파일 불러오고 쓸 함수를 하나씩 만들어놓고 시작하는 게 편하다.
# json 파일 읽기
def read_json_file(file_path):
with open(file_path, "r") as file:
data = json.load(file)
return data
# json 파일 쓰기
def write_json_file(data, file_path):
with open(file_path, 'w') as file:
json.dump(data, file)
그리고 각 파일들이 여러 문항에서 사용되기도 하기 때문에 이렇게 file path
를 만들어 놓고 사용하였다.
users_file_path = os.path.join(os.path.dirname(__file__), "data/users.json")
items_file_path = os.path.join(os.path.dirname(__file__), "data/items.json")
import datetime
import json
import os
from fastapi import FastAPI, HTTPException, Depends
from fastapi.responses import JSONResponse
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel
app = FastAPI()
@app.get("/check")
def get_status():
return {"message": "server is running"}
@app.get("/api/items/{item_id}")
def get_items(item_id:int):
items_data = read_json_file(items_file_path)
item = next((data for data in items_data if data["id"] == item_id), None)
if user:
return JsonResponse(content={"item": {"id": item["id"], "title": item["title"], "price": item["price"]}})
else:
raise HTTPException(detail="Item not found", status_code=404)
type annotation을 활용해서 data validation해준다.
class Item(BaseModel):
title: str
price: int
@app.post("/api/item")
def register_item(data: Item):
try:
write_json_file(data, items_file_path)
return JsonResponse(content={"message": "Item registered successfully"}, status_code=201)
except:
raise HTTPException(detail="Invalid data Format", status_code=400)
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
def create_jwt_token(data: dict, expires_delta: datetime.timedelta):
to_encode = data.copy()
expire = datetime.datetime.utcnow() + expires_delta
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
users_data = read_json_file(users_file_path)
user = next((data for data in users_data if data["username"] == username and data["password"] == password), None)
expires_delta = datetime.timedelta(minutes=60)
access_token = create_jwt_token(data={"sub": user["id"]}, expires_delta=expires_delta)
response_data = {
"data": {"expire": int((datetime.datetime.utcnow() + expires_delta).timestamp() * 1000), "token": access_token}
}
headers = {"Authorization": f"Bearer {access_token}"}
return JSONResponse(content=response_data, headers=headers)
이런 식으로 하면 access token을 생성할 수 있다.
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def validate_token(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
user_id: int = payload.get("sub")
if not user_id:
raise HTTPException(detail="Invalid Token", status=401)
except:
raise HTTPException(
detail="Could not validate credentials",
headers={"WWW-Authorization": "Bearer"},
status_code=401,
)
return user_id
@app.get("/api/users", response_model=User)
async def get_user(user: int = Depends(validate_token)):
users_data = read_json_file(users_file_path)
user = next((data for data in users_data if data["id"] == user_id, None)
return user
host
또는 port
가 정해져있을 때는 다음과 같이 실행한다.
uvicorn main:app --host 0.0.0.0 --port 7777 --reload
그리고 새로운 terminal을 열어 다음과 같이 테스트해볼 수 있다.
curl -X GET "0.0.0.0:7777/check" \
-H 'Content-Type: application/json'
curl -X POST "0.0.0.0:7777/api/item" \
-H 'Content-Type: application/json' \
-d '{
"title": "shirts",
"price": 50000
}'
참고
https://fastapi.tiangolo.com/ko/
https://fastapi.tiangolo.com/ko/tutorial/first-steps/
https://codechacha.com/ko/python-read-write-json-file/
감사합니다. 이런 정보를 나눠주셔서 좋아요.