[FastAPI] 1. Summary

Judy·2023년 3월 15일
0

FastAPI

목록 보기
1/8

Why FastAPI?

Web framework for developing RESTful APIs in Python

  • Pydantic 및 유형 힌트를 기반으로 데이터를 검증, 직렬화 및 역직렬화하고 OpenAPI 문서를 자동으로 생성합니다.

The key features are:

  • 빠름: (Starlette과 Pydantic 덕분에) NodeJS 및 Go와 대등할 정도로 매우 높은 성능. 
    사용 가능한 가장 빠른 파이썬 프레임워크 중 하나.
  • 빠른 코드 작성: 약 200%에서 300%까지 기능 개발 속도 증가. *
  • 적은 버그: 사람(개발자)에 의한 에러 약 40% 감소. *
  • 직관적: 훌륭한 편집기 지원. 모든 곳에서 . 적은 디버깅 시간. 자동완성
  • 쉬움: 쉽게 사용하고 배우도록 설계. 적은 문서 읽기 시간.
  • 짧음: 코드 중복 최소화. 각 매개변수 선언의 여러 기능. 적은 버그.
  • 견고함: 준비된 프로덕션 용 코드를 얻으십시오. 자동 대화형 문서와 함께.
  • 표준 기반: API에 대한 (완전히 호환되는) 개방형 표준 기반: OpenAPI (이전에 Swagger로 알려졌던) 및 JSON 스키마.

Project

Project Link (GitHub)

Structure

.
└── FastAPI
		├── * database.py
		├── * models.py
		├── schemas.py
		├── * crud.py
		├── * main.py
		└── __init__.py

database.py : ORM

SQLAlchemy : python 에서 사용가능한 ORM 라이브러리 (≒ JS - TypeORM)

Create SQLAlchemy engine

engine = create_engine(DB_URL)

Create a SessionLocal class

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
  • sessionmaker
    • 각각의 SessionLocal 클래스 객체는 데이터베이스의 세션이 된다.
    • 추후 사용할 Session 과 이름 충돌을 막기 위해 변수명은 SessionLocal 로.
    • DB의 세션?
      • 데이터베이스 접속을 시작으로, 여러 작업을 수행한 후 접속 종료까지의 전체 기간
      • 세션 내부에는 하나 이상의 트랜잭션이 존재한다
      • 일반적으로 데이터베이스는 여러 곳에서 동시에 접근하여 수많은 세션이 동시에 연결되어 있다.

Create a Base class

Base = declarative_base()
  • 클래스 하나를 리턴받고, 추후 해당 클래스를 상속받아 DB 모델이나 ORM 클래스 생성.
  • 테이블당 어플리케이션이 사용가능한 하나의 모델을 생성할 수 있다

models.py : Create DB Model

  • database.py 에서 만든 Base class 를 import & 상속하여 DB모델 생성
from .database import Base

class reviews(Base):
	# SQLAlchemy의 테이블 이름
    __tablename__ = "reviews"
    id = Column(Integer, primary_key=True, index=True)
    platform = Column(String)
    rating = Column(Integer)
    content = Column(String)
    time = Column(DateTime)

schemas.py : Create initial Pydantic models / schemas

  • DB에 Create 할 때 사용되는 모듈
  • 내 프로젝트에는 사용하지 않았으므로 생략

crud.py : CRUD utils

  • Read
# 이 Session을 통해 db라는 파라미터를 만들고 데이터베이스와 소통할 수 있다.
from sqlalchemy.orm import Session
# models.py : SQLAlchemy model들
# schemas.py : Pydantic models / schemas
import models, schemas

def get_reviews(db: Session, store_id, start, end):    
    # 지정된 기간 내 플랫폼별 리뷰 조회
    reviews = db.query(models.reviews).filter(between(models.reviews.time, start, end)).all()
		#...생략
    return_json = {"daily_count" : daily_count, "all_count" : all_count}
    return return_json

main.py

CORS

와일드카드

  • 모든 출처를 허용하기 위해 목록을 "*" ("와일드카드")로 선언할 수 있음
  • 한계
    • 특정한 유형의 통신만을 허용하며, 쿠키 및 액세스 토큰과 사용되는 인증 헤더(Authoriztion header) 등이 포함된 경우와 같이 자격 증명(credentials)이 포함된 통신은 허용되지 않음
    • 따라서 모든 작업을 의도한대로 실행하기 위해 허용되는 출처를 명시적으로 지정하는 것 추천.

CORSMiddleware 사용

  • CORSMiddleware 임포트.
  • 허용되는 출처(문자열 형식)의 리스트 생성.
  • FastAPI 응용 프로그램에 "미들웨어(middleware)"로 추가.
origins = ["*"]

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Engine 연결

models.Base.metadata.create_all(bind=engine)

Dependency with yield

  • dependency + yield 조합을 통하여 리퀘스트에서 db세션을 생성하고 response 시 DB를 종료하도록 코드를 작성한다
    참고 Link

  • FastAPI에서는 yield를 사용하여 dependency 가 끝나면 몇가지 작업을 수행할 수 있다.

    • ex : 데이터베이스를 생성한 뒤 사용하고, 사용이 끝났으면 데이터베이스를 종료
    async def get_db():
        db = DBSession()
        try:
            yield db
        finally:
            db.close()
    • response를 보내기 전까지 yield 까지의 코드만이 실행된다.
    • response가 전달되면 마지막으로 finally 이후 코드가 수행된다.
  • Middleware vs Dependency + yield

    • 미들웨어는 좀더 많은 코드와 복잡도를 요구한다
    • 미들웨어는 async funtion이여야 한다.
    • 만약 미들웨어에 wait가 있을경우 퍼포먼스에 문제가 생길수 있다.
    • 미들웨어는 매 리퀘스트마다 실행되므로 매 리퀘스트마다 DB에 접속한다
  • 마지막 이유로 미들웨어에 db를 쓰지말고 Dependency + yield 조합을 사용하자

  • 디펜던시로 사용할때 자료형을 db의 자료형을 Session으로 지정해 준다.

  • 마지막으로 path operation을 구현시켜주면 된다.

    @app.get("/")
    async def get_products(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
        products = crud.get_products(db, skip=skip, limit=limit)
        return products

Query Parameter

참고 Link

http://127.0.0.1:8000/reviews?storeId=0&startDate=20221201&endDate=20231201
# main.py
@app.get("/reviews")
async def get_reviews(storeId: int = 0, startDate: int = 20221201, endDate: int = 20230101, db: Session = Depends(get_db)):
	products = crud.get_reviews(db, store_id=storeId, start=startDate, end=endDate)
	return products
  • 기본적으로 query parameter에 값을 실어서 보내면 데이터형은 String이 된다.
  • 예제와 같이 Query parameter에 데이터 타입을 명시할 경우 FastAPI 는 자동으로 데이터 타입을 int 형으로 변경해 준다.

Reference

공식문서
https://fastapi.tiangolo.com/
공식문서 번역
https://lucky516.tistory.com/109

https://mumin-blog.tistory.com/338
https://jongsky.tistory.com/17

Debug Issue
https://fastapi.tiangolo.com/tutorial/debugging/
https://incomeplus.tistory.com/187

CRUD 구현 시 참고
https://breezymind.com/fastapi-crud-api/

profile
NLP Researcher

0개의 댓글