POST

All
Product
Team
Tech
DocVLM: Make Your VLM an Efficient Reader
  • 최윤진
  1. Tech
Python 3.10 신규 문법 : Parenthesized context managers와 PEG Parser
  • S
    seunghoChoe
  1. Tech
UReader: Universal OCR-free Visually-situated Language Understanding with Multimodal Large Language Model
  • 최윤진
  1. Tech
[팀 소개편] KPMG Lighthouse는 어떤 팀인가요?
  • L
    Lighthouse
  1. Team
[챕터 소개편] Backend Chapter를 소개합니다
  • L
    Lighthouse
  1. Team
[챕터 소개편]Frontend Chapter를 소개합니다
  • L
    Lighthouse
  1. Team
[챕터 소개편] AI Chapter를 소개합니다
  • L
    Lighthouse
  1. Team

FastAPI 특징 with Pydantic

Created by
  • D
    donggyun_woo
Created at
💬
이번 글에서는 python FastAPI의 특징과 FastAPI내에서 Pydantic을 사용한 코드를 확인해 보겠습니다.

Fast API

Fast API란?

FastAPI는 Python 프레임워크 중 하나입니다. Python 프레임워크들 중 django, flask 와 같이 비교를 많이 하며, 빠른 속도로 인해 인기가 많아진 프레임워크입니다.
FastAPI에서 제공하는 기능들을 간략히 보면 아래와 같습니다.
👍
API 문서 자동 생성 (Swagger와 ReDoc 스타일 동일)
의존성 주입 위주의 설계를 통한 DB 등에 대한 관리 편리
비동기 동작으로 빠른 성능 보장 (Starlette)
Pydantic을 사용한 Validation 체크
뛰어난 공식문서 가이드
Python Framework 깃허브 스타
github star history 그래프를 보면 FastAPI(노란색)의 스타가 급격히 증가하는 것을 확인 할 수 있습니다.
그래프를 통해 FastAPI를 많이 사용한다는 의미는 될 수 없겠지만, 개발자들 사이에서 관심을 많이 갖고 있는것은 확인 할 수 있을것 같습니다.

FastAPI의 특징

특징들을 Fast API 공식문서를 통해 자세하게 확인해 보겠습니다.
💬
파이썬 3.8+ 버전의 Type hint를 사용하는 트랜디하고 높은 성능을 가진 파이썬 프레임워크
빠름: NodeJS 및 Go와 동등한 매우 높은 성능을 제공
실제 파이썬 기반의 프레임워크들을 비교한 내용을 확인해 보면 성능이 상위에 존재하는 것을 확인 할 수 있습니다.
빠른 코딩: 기능 개발 속도를 약 200%~300% 향상
버그 감소: 인간(개발자)이 유발한 오류의 약 40% 감소
직관적: 뛰어난 편집기 지원. 디버깅 시간이 줄어듭니다.
간단: 사용 및 학습이 용이하도록 설계되었습니다. 문서를 읽는 시간이 줄어듭니다.
짧게: 코드 중복을 최소화합니다. 버그 수를 줄입니다.
견고함: production-ready code를 얻을 수 있음.
🙋
To write production-ready code in Python,
it is important to understand the importance of code modularization, following PEP8 style guidelines, using meaningful variable, class, and function names, organizing your code, and writing thorough documentation.
표준 기반: API의 개방형 표준인 OpenAPI(이전의 Swagger)와 JSON Schema를 기반으로 합니다.

Starlette & Pydantic

Fast API는 빠른 속도와 코딩이 가능하고, 직관적이라고 합니다. 이런 특징을 갖게 된 이유는 StarlettePydantic 등을 사용한 결과이기도 합니다.

Starlette

Starlette에 대해 알기 전에 먼저 ASGI, WSGI에 대해 알아 보겠습니다.
WSGI(Web Server Gateway Interface)
WSGI는 파이썬 웹 응용 프로그램을 위한 것
웹서버와 파이썬으로 작성된 웹 응용 프로그램 간의 표준 인터페이스
gunicorn
기존의 동기(django, flask)로 작동되는 웹프레임워크들은 gunicorn을 많이 사용했습니다.
ASGI(Asynchronous Server Gateway Interface)
ASGI의 공식문서에서는 따르면, ASGI는 WSGI의 정신적 계승자로, 비동기 가능 Python 웹 서버, 프레임워크 및 애플리케이션 간의 표준 인터페이스를 제공하기 위한 것
WSGI가 동기 Python 앱에 대한 표준을 제공했다면 ASGI는 WSGI 이전 버전과의 호환성 구현과 여러 서버 및 애플리케이션 프레임워크를 통해 비동기 및 동기 앱 모두에 대한 표준을 제공합니다.
다시 Starlette으로 돌아가면, 공식 문서에서는 Python에서 비동기 웹 서비스를 구축하는 데 이상적인 경량 ASGI 프레임워크/툴킷으로 설명 합니다.
그리고 FastAPI는 이 Starlette을 기반으로 개발이 되었고, 그로 인해 비동기 동작이 가능한 서버를 구현합니다.
아래의 이미지 처럼 FastAPI앞에 ASGI의 하나인 uvicorn을 넣어서 비동기로 서버를 운영합니다.

Pydantic

Pydantic은 파이썬의 Type annotation(type hint)을 활용하여 data validataion(검증)과 세팅을 관리해 주는 파이썬 라이브러리입니다.
FastAPI에서 Pydantic이 하는 역할은 다음과 같습니다.
API 문서 자동화
입출력 항목의 갯수와 타입을 설정
입출력 항목의 필수값 체크
입출력 항목의 데이터 검증

Pydantic 장점

FastAPI에서 Pydantic을 사용하는 이점은 다음과 같습니다.
데이터 검증 및 직렬화 최적화 : Pydantic은 데이터 검증 및 직렬화(데이터 구조를 문자열 형태로 변환) 과정을 효율적으로 처리합니다. 이는 FastAPI가 요청을 빠르게 분석하고 응답 데이터를 신속하게 생성하는데 도움을 줍니다.
타입 힌트와 통합 : Pydantic은 Python의 타입 힌트와 밀접하게 통합되어 있어 명확한 타입 정의를 사용할 수 있게 합니다. 이를 통해 런타임 오류를 줄이고 성능을 개선합니다.
오류 처리 : Pydantic은 유효성 검증을 통해 발생할 수 있는 오류를 잡아내고, 에러 메시지로 반환하여 안정적인 성능을 유지하는데 기여합니다.
코드의 간결성과 유지보수성 : Pydantic을 사용하면 데이터 모델을 쉽게 유지보수 할 수 있습니다.

Pydantic - 적용 예제 코드

from typing import Union from fastapi import FastAPI from pydantic import BaseModel, EmailStr class BaseUser(BaseModel): user_id: int username: str email: EmailStr full_name: Union[str, None] = None # Type hint를 통해 스키마를 설정할 수 있다. class UserIn(BaseUser): # 상속을 받을 수 있어 코드를 줄일 수 있다. password: str @app.put("/items/{item_id}") async def update_item(item_id: int, item: Item, user: BaseUser): results = {"item_id": item_id, "item": item, "user": user} return results @app.post("/user/") async def create_user(user: UserIn) -> BaseUser: # 결과값에 대한 정의 이다. # user: UserIn => 사용자를 생성할 때 받아야하는 request body 값을 정의한다. return user
Pydantic - 데이터 검증 예제 코드
from typing import Union from pydantic import BaseModel ... class Item(BaseModel): name: str description: Union[str, None] = None price: float tax: Union[float, None] = None ... @app.put("/items/{item_id}") async def update_item( item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)], q: Union[str, None] = None, item: Union[Item, None] = None, ): results = {"item_id": item_id} if q: results.update({"q": q}) if item: results.update({"item": item}) return results
update를 하는 API가 있을 때, request body 값에 들어가야하는 내용을 Pydantic을 사용하여 데이터 스키마를 정의합니다.
Type hint를 활용해서 데이터 속성의 타입을 정의 할 수 있습니다.
FastAPI에서 제공하는 OpenAPI(swagger)로 확인을 해보면 path parameter, query parameter, request body를 확인 할 수 있고, 테스트가 가능합니다.
request body 값으로 미리 설정한 Pydantic에 맞게 실행을 하게 된다면 정상적으로 200 을 반환합니다.
// request body { "name": "string", "description": "string", "price": 1, "tax": 0 } // response body **{ "item_id": 1, "q": "test", "item": { "name": "string", "description": "string", "price": 1, "tax": 0 } } // log** >>> INFO: 127.0.0.1:8630 - "PUT /items/1?q=test HTTP/1.1" 200 OK
하지만 검증에 틀리는 경우에는 다음과 같습니다.
// request body { "name": "string", "description": "string", "price": "ff1", # float 값이 아닌 string 값인 경우 "tax": 0 } // response body { "detail": [ { "type": "float_parsing", "loc": [ "body", "price" ], "msg": "Input should be a valid number, unable to parse string as a number", "input": "ff1", "url": "https://errors.pydantic.dev/2.5/v/float_parsing" } ] } // log >>> INFO: 127.0.0.1:8693 - "PUT /items/1?q=test HTTP/1.1" 422 Unprocessable Entity

마무리

이번 세션을 준비하면서 Fast API에 대해 공부를 했습니다.
공식 가이드 문서가 잘 되어 있고, 관련된 기술 블로그들도 생각보다 많아서 참고하기에 좋았습니다.

참고 사이트 및 문서