FastAPI 타입
- FastAPI의 타입
- 파이썬 타입
- 동기 부여
- 타입 선언
- 타입으로서의 클래스
- Pydantic 모델
- > User id=123 name=’John Doe’ signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
- > 123
FastAPI의 타입
파이썬 타입
파이썬은 선택적으로 “타입 힌트(type hints)”를 지원한다. 이러한 타입 힌트들은 변수의 타입을 선언할 수 있게 해주는 특수한 구문이다.
FastAPI는 타입 힌트에 기반을 두고 있으며, 이는 많은 장점과 이익이 있다.
동기 부여
def get_full_name(first_name, last_name):
full_name: first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
이 프로그램을 실행한 결과값
John Doe
함수는 아래와 같이 실행된다.
first_name과last_name을 받는다.title()로 각 첫 문자를 대문자로 변환시킨다.- 두 단어를 중간에 공백을 두고 연결한다.
타입 추가하기
위의 코드에서 한 줄만 수정해본다.
first_name, last_name
을 아래와 같이 바꾼다.
first_name: str, last_name: str
이게 “타입 힌트” 이다.
def get_full_name(first_name: str, last_name: str):
full_name: first_name.title() + " " + last_name.title()
return full_name
print(get_full_name("john", "doe"))
타입 힌트는 다음과 같이 기본 값을 선언하는 것과는 다르다.
first_name="john", last_name="doe"
이는 다른 것이다.
등호(=) 대신 콜론(:)을 쓰고 있다. 일반적으로 타입 힌트를 추가한다고 해서 특별하게 어떤 일이 일어나지도 않는다.
타입 선언
Simple 타입
str 뿐 아니라 모든 파이썬 표준 타입을 선언할 수 있다.
예를 들면
intfloatboolbytes
def get_time(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes):
return item_a, item_b, item_c, item_d, item_e
타입 매개변수를 활용한 Generic(제네릭) 타입
dict, list, set, tuple 과 같은 값을 저장할 수 있는 데이터 구조가 있고, 내부의 값은 각자의 타입을 가질 수도 있다. 타입과 내부 타입을 선언하기 위해서는 파이썬 표준 모듈인 typing을 이용해야 한다.
구체적으로는 아래 타입 힌트를 지원한다.
List
예를 들면, str의 list인 변수를 정의해본다. typing에서 List(대문자 L)를 import 한다.
from typing import List
def process_items(items: List[str]):
for item in items:
print(item)
- python 3.9 버전부터
def process_items(items: list[str]): for item in items: print(item)
콜론(:) 문법을 이용하여 변수를 선언한다. 타입으로는 List를 넣어준다. 이 때 배열은 내부 타입을 포함하는 타입이기 때문에 대괄호 안에 넣어준다.
이는 “items은 list인데, 배열에 들어있는 아이템 각각은 str이다” 라는 뜻이다.
tuple과 set도 동일하게 선언할 수 있다.
from typing import Set, Tuple
def process_items(items_t: Tuple[int, int, str], items_s: Set[bytes]):
return items_t, items_s
- python 3.9 버전부터
def process_items(items_t: tuple[int, int, str], items_s: set[bytes]): return items_t, items_s
이 뜻은 아래와 같다
- 변수
items_t는 차례대로int,int,str인tuple이다. - 변수
items_s는 각 아이템이bytes인set이다.
dict를 선언하려면 컴마로 구분된 2개의 파라미터가 필요하다. 첫 번째 매개변수는 dict의 키(key)이고, 두 번째 매개변수는 dict의 값(value)이다.
from typing import Dict
def process_items(prices: Dict[str, float]):
for item_name, item_price in prices.items():
print(item_name)
print(item_price)
- python 3.9 버전부터
def process_items(prices: dict[str, float]): for item_name, item_price in prices.items(): print(item_name) print(item_price)
이 뜻은 아래와 같다.
- 변수
prices는dict이다.dict의 키(key)는str타입이다. (각 아이템의 이름(name))dict의 값(value)는float타입이다. (각 아이템의 가격(price))
str과 같이 타입을 선언할 때 Optional을 쓸 수도 있는데, “선택적(Optional)”이기 때문에 None도 될 수 있다.
from typing import Optional
def say_hi(name: Optional[str] = None):
if name is not None:
print(f"Hey {name}!")
else:
print("Hello World")
Optional[str]을 str 대신 쓰게 되면, 특정 값이 실제로는 None이 될 수도 있는데 항상 str이라고 가정하는 상황에서 에디터가 에러를 찾게 도와줄 수 있다.
Generic(제네릭) 타입
이 타입은 대괄호 안에 매개변수를 가지며, 종류는:
ListTupleSetDictOptional- …등등
위와 같은 타입은 Generic(제네릭) 타입 혹은 Generics(제네릭스)라고 불린다.
타입으로서의 클래스
변수의 타입으로 클래스를 선언할 수도 있다.
이름(name)을 가진 Person 클래스가 있다고 해본다.
class Person:
def __init__(self, name: str):
self.name = name
def get_person_name(one_person: Person):
return on_person.name
그렇게 하면 변수를 Person이라고 선언할 수 있게 된다.
Pydantic 모델
Pydantic은 데이터 검증(Validation)을 위한 파이썬 라이브러리이다. 속성을 포함한 클래스 형태로 “모양(shape)”을 선언할 수 있다. 그리고 각 속성은 타입을 가지고 있다.
이 클래스를 활용해서 값을 가지고 있는 인스턴스를 만들게 되면, 필요한 경우에는 적당한 타입으로 변환까지 시키기도 해서 데이터가 포함된 객체를 반환한다.
그리고 결과 객체에 대해서는 데이터의 도움을 받을 수 있게 된다.
Pydantic 공식 문서 예시
from datetime import datetime
from typing import List, Union
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str = "John Doe"
signup_ts: Union[datetime, None] = None
friends: List[int] = []
external_data = {
"id": "123",
"signup_ts": "2017-06-01 12:22",
"friends": [1, "2", b"3"],
}
user = User(**external_data)
print(user)
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
# > 123
- Python 3.9버전 부터 ```python from datetime import datetime from typing import Union
from pydantic import BaseModel
class User(BaseModel): id: int name: str = “John Doe” signup_ts: Union[datetime, None] = None friends: list[int] = []
external_data = { “id”: “123”, “signup_ts”: “2017-06-01 12:22”, “friends”: [1, “2”, b”3”], } user = User(**external_data) print(user)
> User id=123 name=’John Doe’ signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
> 123
- Python 3.10 버전 부터
```python
from datetime import datetime
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str = "John Doe"
signup_ts: datetime | None = None
friends: list[int] = []
external_data = {
"id": "123",
"signup_ts": "2017-06-01 12:22",
"friends": [1, "2", b"3"],
}
user = User(**external_data)
print(user)
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
# > 123
FastAPI에서의 타입 힌트
FastAPI는 여러 부분에서 타입 힌트의 장점을 취하고 있다. FastAPI에서 타입 힌트와 함께 매개변수를 선언하면 장점은:
- 에디터 도움.
- 타입 확인.
FastAPI는 같은 정의를 아래에도 적용한다.
- 요구사항 정의: 요청 경로 매개변수, 쿼리 매개변수, 헤더, 바디, 의존성 등
- 데이터 변환: 요청에서 요구한 타입으로
- 데이터 검증
- 각 요청마다
- 데이터가 유효하지 않은 경우에는 자동으로 에러를 발생한다.
- 각 요청마다
- OpenAPI를 활용한 API 문서화
- 자동으로 상호작용하는 유저 인터페이스에 쓰이게 된다.