Python의 타입 힌트란?

Python은 동적 타입 언어로, 변수에 별도의 타입을 선언하지 않아도 코드를 실행할 수 있다. 하지만 타입 힌트(Type Hints) 는 선택적으로 사용할 수 있는 기능으로, 변수의 타입을 명시적으로 선언하여 코드의 가독성과 유지보수성을 높인다.

타입 힌트를 사용하면 다음과 같은 이점이 있다:

  • 에디터 도움: 자동 완성과 실시간 오류 감지가 강화된다.
  • 코드 안정성 증가: 타입 오류를 사전에 방지할 수 있다.
  • 문서화 개선: 코드의 의도를 명확히 표현할 수 있다.

기본적인 타입 힌트 사용법

함수 매개변수와 반환값에 타입 힌트 추가

타입 힌트는 변수 이름 뒤에 콜론(:)과 타입을 지정하며, 반환값의 타입은 함수 선언부 뒤에 ->를 사용한다.

# Python 3.8+
def get_full_name(first_name: str, last_name: str) -> str:
	full_name = first_name.title() + " " + last_name.title()
	return full_name
 
print(get_full_name("john", "doe"))
  • first_name: str: first_name은 문자열이어야 한다.
  • -> str: 함수는 문자열을 반환한다.

타입 힌트가 주는 개발 생산성 향상

타입 힌트를 사용하면 에디터가 변수를 추론하고 자동 완성을 제공할 수 있다. 아래 예시를 통해 에디터의 도움을 확인해보자:

def capitalize_names(name: str) -> str:
	return name.capitalize()
 
# 에디터에서 `name.` 뒤에 메서드 자동 완성 지원
capitalize_names("python")

타입이 없는 경우 자동 완성 기능이 제한되거나 누락될 수 있지만, 타입을 명시하면 해당 타입과 관련된 메서드가 자동 완성된다.

타입 힌트와 데이터 구조

리스트(List)

리스트의 각 항목 타입을 명시하려면, typing 모듈의 List를 사용한다.

from typing import List
 
def process_items(items: List[str]):
	for item in items:
		print(item)
 
process_items(["apple", "banana", "cherry"])

튜플(Tuple)과 세트(Set)

튜플과 세트는 요소별 타입을 지정할 수 있다.

from typing import Tuple, Set
 
def process_data(data: Tuple[int, str], values: Set[float]):
	print(data, values)
 
process_data((1, "example"), {1.0, 2.5})
  • Tuple[int, str]: 첫 번째 요소는 정수, 두 번째 요소는 문자열.
  • Set[float]: 각 요소는 부동소수점 숫자.

딕셔너리(Dictionary)

딕셔너리는 키와 값의 타입을 각각 지정할 수 있다.

from typing import Dict
 
def calculate_total(prices: Dict[str, float]):
	for item, price in prices.items():
		print(f"{item}: {price}")
 
calculate_total({"apple": 0.5, "banana": 0.3})
  • Dict[str, float]: 키는 문자열, 값은 부동소수점 숫자.

Optional 타입

Optional은 특정 변수가 None일 수도 있음을 명시한다.

from typing import Optional
 
def greet(name: Optional[str] = None):
	if name:
		print(f"Hello, {name}!")
	else:
		print("Hello, World!")
 
greet("Alice")
greet()
  • Optional[str]: name은 문자열 또는 None일 수 있다.

Pydantic과 타입 힌트

Pydantic은 Python의 데이터 검증 및 설정 관리를 위한 라이브러리로, 타입 힌트를 기반으로 데이터의 유효성을 검사한다.

특징Python 타입 힌트Pydantic
주요 역할코드 가독성과 에디터 자동 완성을 위한 선언적 타입 지정데이터 검증 및 타입 변환을 자동 처리
데이터 검증데이터 검증 기능 없음데이터 유효성 검사 및 자동 변환 지원
실행 시 동작컴파일 또는 에디터 레벨에서만 도움 제공런타임에서도 유효성 검증 및 데이터 처리 수행
기본 제공 기능표준 타입(int, str 등) 및 일부 컬렉션 타입 지원추가로 복잡한 데이터 구조(datetime, 커스텀 클래스 등)까지 처리 가능
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]
  • User 클래스는 데이터의 구조와 타입을 정의하며, Pydantic이 자동으로 타입 변환과 검증을 수행한다.

Pydantic은 데이터를 자동으로 변환하고 검증하므로, 외부 입력 데이터의 신뢰성을 확보할 수 있다.

FastAPI와 타입 힌트

FastAPI는 타입 힌트를 기반으로 다음과 같은 기능을 제공한다:

  • 데이터 검증: 요청 데이터가 타입에 맞지 않으면 자동으로 오류를 반환.
  • 문서화: OpenAPI 스펙을 자동 생성하여 상호작용 가능한 API 문서를 제공.
  • 데이터 변환: 입력값을 선언된 타입으로 자동 변환.
from fastapi import FastAPI
from pydantic import BaseModel
 
app = FastAPI()
 
class Item(BaseModel):
	name: str
	price: float
	description: str | None = None
 
@app.post("/items")
def create_item(item: Item):
	return {"name": item.name, "price": item.price, "description": item.description}

작동 방식

  1. 요청 데이터의 자동 검증
    • 클라이언트가 /items/로 데이터를 POST하면 FastAPI가 자동으로 데이터를 Item 모델에 매핑.
    • 필수 필드(name, price) 누락 시 오류 반환.
  2. 유효성 검사 실패 시 자동 에러 반환
    • 데이터가 정의된 타입(str, float)과 맞지 않을 경우, HTTP 422 에러와 함께 상세 오류 반환.
  3. 자동 문서화
    • FastAPI는 OpenAPI 스펙을 생성하여 API 문서를 자동으로 작성.
    • /docs 엔드포인트에서 상호작용 가능한 문서 확인 가능.

결론

Python의 타입 힌트는 코드의 품질을 높이고, 유지보수를 쉽게 만들어 준다. 특히 FastAPIPydantic과 같은 프레임워크와 결합하면 데이터 검증, 문서화, 타입 추론과 같은 이점을 제공한다.