Python 타입 힌트: 더 안전하고 명확한 코드 작성

Backend2026-09-13TryQuickToolBox

여러분은 아마 입력에 따라 다른 타입을 반환하는 Python 함수나 중간에 타입이 바뀌는 변수를 본 적이 있을 것입니다. 이러한 모호함은 런타임 오류를 일으키지만, 미리 잡을 수 있었던 문제입니다. Python 타입 힌트는 예상 타입을 명시할 수 있게 하여 코드를 자기 문서화하고, 정적 분석 도구가 실행 전에 실수를 잡아내도록 도와줍니다.

이 글에서는 기본 어노테이션부터 고급 패턴까지 Python에서 타입 힌트를 효과적으로 사용하는 방법과, 이것이 어떻게 더 안전하고 명확한 코드에 기여하는지 살펴봅니다.

Python 타입 힌트란?

타입 힌트(타입 어노테이션이라고도 함)는 Python 3.5(PEP 484)에서 도입된 문법으로, 변수, 함수 매개변수, 반환 값의 예상 타입을 지정할 수 있습니다. 런타임에 강제되지는 않지만 mypy, pyright, IDE와 같은 정적 타입 검사기가 타입 관련 오류를 감지하는 데 사용됩니다.

예를 들어:

def greet(name: str) -> str:
    return f"Hello, {name}"

여기서 name: str은 name이 문자열이어야 함을 나타내고, -> str은 함수가 문자열을 반환함을 나타냅니다.

타입 힌트를 사용하는 이유

기본 타입 어노테이션

변수, 함수 매개변수, 반환 타입을 어노테이션할 수 있습니다.

변수

age: int = 30
name: str = "Alice"

함수

def add(a: int, b: int) -> int:
    return a + b

컬렉션

리스트, 딕셔너리 등에는 typing 모듈(Python 3.9+에서는 내장 제네릭)을 사용하세요:

from typing import List, Dict

def process(items: List[str]) -> Dict[str, int]:
    return {item: len(item) for item in items}

Python 3.9+에서는 list[str]과 dict[str, int]를 직접 사용할 수 있습니다.

고급 타입 힌트

코드가 커지면 더 복잡한 시나리오를 만나게 됩니다. 다음은 몇 가지 고급 기능입니다.

Optional과 Union

Optional[T]는 Union[T, None]의 축약형으로, T 타입이거나 None일 수 있는 값을 나타냅니다.

from typing import Optional

def find_user(user_id: int) -> Optional[str]:
    # returns username or None if not found
    ...

Python 3.10+에서는 | 연산자를 사용할 수 있습니다: str | None.

Callable

함수를 인자로 받을 때:

from typing import Callable

def apply_func(func: Callable[[int], int], value: int) -> int:
    return func(value)

제네릭

타입 변수를 사용하여 재사용 가능한 컴포넌트를 만드세요:

from typing import TypeVar, List

T = TypeVar('T')

def first(items: List[T]) -> T:
    return items[0]

TypedDict

고정된 키 집합과 값 타입을 가진 딕셔너리용:

from typing import TypedDict

class User(TypedDict):
    name: str
    age: int

def greet(user: User) -> str:
    return f"Hello, {user['name']}"

정적 타입 검사기 사용하기

타입 힌트는 검사할 때만 유용합니다. 인기 있는 도구로는 mypy, pyright, pyre가 있습니다. mypy 사용법을 알아보겠습니다.

  1. mypy 설치: pip install mypy
  2. 코드에 실행: mypy your_script.py
  3. 보고된 오류 수정.

예를 들어, 다음이 주어졌을 때:

def add(a: int, b: int) -> int:
    return a + b

add("1", "2")

mypy는 다음과 같이 보고합니다: error: Argument 1 to "add" has incompatible type "str"; expected "int".

mypy.ini 또는 pyproject.toml 파일을 통해 mypy를 구성하여 더 엄격한 검사를 적용할 수 있습니다.

타입 힌트 모범 사례

흔한 함정과 피하는 방법

실전 타입 힌트: 작은 예제

숫자 리스트를 처리하고 평균을 반환하는 함수를 생각해 보세요. 타입 힌트가 없으면 어떤 타입이 예상되는지 불분명합니다.

def average(numbers):
    return sum(numbers) / len(numbers)

타입 힌트를 사용하면:

from typing import List

def average(numbers: List[float]) -> float:
    return sum(numbers) / len(numbers)

이제 누군가 문자열 리스트를 전달하면 mypy가 이를 지적합니다.

워크플로우에 타입 힌트 통합하기

타입 힌트를 최대한 활용하려면 개발 프로세스에 통합하세요:

  1. 기존 코드베이스에 점진적으로 타입 힌트를 추가하세요.
  2. IDE가 타입 오류를 표시하도록 구성하세요.
  3. CI 파이프라인에 타입 검사 단계를 추가하세요.
  4. pre-commit 훅을 사용하여 커밋 전에 mypy를 실행하세요.

예를 들어, 간단한 GitHub Actions 워크플로우 단계:

- name: Type check
  run: mypy .

FAQ

타입 힌트가 런타임 성능에 영향을 미치나요?

아니요, 타입 힌트는 런타임에 무시됩니다. __annotations__에 저장되지만 실행 속도에는 영향을 주지 않습니다.

이전 Python 버전에서 타입 힌트를 사용할 수 있나요?

타입 힌트는 Python 3.5에서 도입되었습니다. 이전 버전에서는 주석 기반 어노테이션(예: # type: int)을 사용할 수 있지만, 지원되는 Python 버전으로 업그레이드하는 것이 좋습니다.

타입 힌트에서 List와 list의 차이는 무엇인가요?

typing의 List는 Python 3.5-3.8에서 사용됩니다. Python 3.9+에서는 내장 list를 직접 사용할 수 있습니다. 둘 다 타입 검사에 동등합니다.

코드 품질을 개선할 준비가 되셨나요? 오늘 한 함수에 타입 힌트를 추가하고 mypy를 실행하여 이점을 확인해보세요. 더 많은 개발자 도구를 원하시면 JSON Formatter를 확인하여 JSON 데이터를 손쉽게 예쁘게 만들고 검증하세요.