from __future__ import annotations – 파이썬에서 타입 힌트의 미래를 여는 문장

키워드: __future__, annotations, PEP 563, PEP 649, Python 3.7+


1. 왜 __future__가 필요했을까?



파이썬은 1990년대 초반부터 동적 타입 언어로 설계되었습니다.
하지만 대규모 프로젝트가 늘어나면서 정적 타입 검사코드 가독성이 중요해졌습니다.
이를 위해 파이썬은 타입 힌트(type hints)를 도입했고, typing 모듈이 생겼습니다.

하지만 초기 타입 힌트는 런타임에 바로 해석되기 때문에 다음과 같은 문제가 있었습니다.

문제 예시
순환 참조 class A: pass
class B(A): pass
타입 힌트에서 A를 바로 사용하면 NameError 발생
지연 평가 from typing import List
def f(x: List[int]) -> List[int]: ...
함수 정의 시점에 List가 이미 import 되어 있어야 함
문자열 지연 def f(x: "MyClass") -> "MyClass": ...
문자열로 타입을 지연시키려면 __future__를 사용해야 함

이러한 문제를 해결하기 위해 PEP 563(Python 3.7)에서 from __future__ import annotations를 도입했습니다.


2. from __future__ import annotations란?

정의: 파이썬 3.7부터 도입된 기능으로, 모든 타입 힌트를 문자열로 지연 평가하도록 해줍니다.

핵심 동작

  • 함수/메서드 정의 시점에 타입 힌트가 문자열 형태로 저장됩니다.
  • 실제 타입이 필요할 때(예: typing.get_type_hints)에 지연 평가가 수행됩니다.
  • 순환 참조가 있는 경우에도 NameError 없이 정상 동작합니다.

사용 예시

# without __future__
class Node:
    def __init__(self, value: int, next: 'Node' = None):
        self.value = value
        self.next = next

# with __future__
from __future__ import annotations

class Node:
    def __init__(self, value: int, next: Node | None = None):
        self.value = value
        self.next = next

주의: __future__를 사용하면 모든 타입 힌트가 문자열이 되므로, typing.get_type_hints 같은 함수가 필요할 때는 typing 모듈이 자동으로 문자열을 평가합니다.


3. PEP 563 이후의 변화



PEP 649 – 지연 평가의 재정의

  • Python 3.11에서 PEP 649가 도입되었습니다.
  • __future__를 사용해도 지연 평가실제 필요할 때만 수행됩니다.
  • typing.get_type_hints캐시를 사용해 성능을 개선했습니다.

Python 3.12 이후

  • PEP 649완전 구현되면서 __future__를 사용해도 지연 평가더 효율적이 되었습니다.
  • from __future__ import annotations기본 동작이므로, 대부분의 경우 별도 선언이 필요 없습니다.

4. 실전 팁

상황 권장 방법 이유
순환 참조 from __future__ import annotations NameError 방지
대규모 프로젝트 __future__ 선언 + typing.get_type_hints 타입 검사 시 성능 향상
Python 3.11+ __future__ 선언 생략 가능 기본 동작이 지연 평가
문자열 타입 힌트 typing.TYPE_CHECKING 사용 런타임에 불필요한 import 방지

예시: typing.TYPE_CHECKING과 함께 사용

from __future__ import annotations
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .module_a import ClassA

class MyClass:
    def method(self, obj: ClassA) -> None:
        ...
  • TYPE_CHECKING정적 타입 검사기에서만 True가 되므로, 런타임에 import가 발생하지 않습니다.

5. 마무리

  • from __future__ import annotations타입 힌트의 지연 평가를 가능하게 해, 순환 참조런타임 오류를 방지합니다.
  • Python 3.11 이후에는 기본 동작이 지연 평가이므로, 대부분의 경우 별도 선언이 필요 없습니다.
  • 여전히 Python 3.7~3.10을 사용하거나, 명시적 지연 평가가 필요한 경우에 유용합니다.

Tip: 프로젝트에 __future__를 추가할 때는 코드베이스 전체에 적용해 일관성을 유지하세요.
또한, 정적 타입 검사기(mypy, pyright 등)와 함께 사용하면 코드 품질을 한층 끌어올릴 수 있습니다.


추가 자료
- PEP 563: https://www.python.org/dev/peps/pep-0563/
- PEP 649: https://www.python.org/dev/peps/pep-0649/
- mypy 공식 문서: https://mypy.readthedocs.io/en/stable/cheat_sheet.html


관련글 보기 : 아래의 글도 확인해보세요!