C.W.K.
Stream
Lesson 01 of 05 · published

기본 타입 힌트 — 사고를 도와주는 어노테이션

~22 min · type-hints, annotation, Optional, Union

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

타입 힌트는 런타임 동작 안 바꿔

Python 타입 힌트는 *어노테이션*. 소스 코드에 앉아있고, 함수의 __annotations__ 에 저장, 정적 타입 체커 (mypy, pyright) 와 IDE 가 읽음. Python 자체가 런타임에 강제 X. def f(x: int) -> str: 가 런타임에 list 받음 — 계약은 도구 레벨, 인터프리터 X.

기본 문법

파라미터에 : type, 반환값에 -> type. 변수도 : type. 필요한 기본 타입 — int, float, str, bool, None, bytes. 컨테이너엔 현대 Python (3.9+) 가 소문자 — list[int], dict[str, int], tuple[int, str], set[str]. typing 의 대문자 List, Dict 는 옛 스타일, 여전히 작동, 근데 이젠 소문자 선호.

Optional / Union / | 연산자

Optional[X]X | None — "X 또는 None". Union[X, Y]X | Y (3.10+). 파이프 문법이 현대 idiom, import 된 이름 여전히 가능 but 더 안 읽힘. def f(x: int | None = None) -> str | None: 가 "없을 수도" 의 표준 모양.

Any — 타입 체커 escape hatch

Any 가 "체크 안 함" 의미. 타입 체커가 Any 값에 어떤 연산도 받음. 타입 없는 라이브러리 인터페이스 또는 진짜 동적 데이터에 유용. 어디나 뿌리지 마 — 타이핑 의미 없게 함. "어떤 객체" 의미면 object (체크됨), Any 는 opt-out 에 예약.

원칙: 타입 힌트 = 체크되는 문서. 함수가 뭘 기대하고 뭘 반환하는지 독자에게, 편집 시점에 실수 잡는 형태로 알려줘. 비용 작음, 버그 방지 가치는 코드베이스 크기에 비례. 현대 Python 스타일 — 모든 거 타입 힌트, 타이핑이 이제 디폴트 기대.

Code

기본 어노테이션·python
def greet(name: str, age: int) -> str:
    return f"hi {name}, age {age}"

# 변수 어노테이션
user_id: int = 42
users: list[str] = ["alice", "bob"]
config: dict[str, int] = {"port": 8000, "workers": 4}

# 어노테이션이 함수에 저장
print(greet.__annotations__)
# {'name': <class 'str'>, 'age': <class 'int'>, 'return': <class 'str'>}

# 런타임은 강제 X — 런타임에 작동, mypy 가 잡음
greet(123, "oops")
현대 컨테이너 타입 — 소문자·python
# 옛 스타일 (여전히 작동)
from typing import List, Dict, Tuple, Set
def old_style(items: List[int]) -> Dict[str, int]:
    return {str(i): i for i in items}

# 현대 스타일 (3.9+) — 선호
def modern(items: list[int]) -> dict[str, int]:
    return {str(i): i for i in items}

# Tuple — 고정 크기와 가변 크기
Point = tuple[float, float]                  # 정확히 2 floats
MixedTuple = tuple[int, str, bool]            # 위치별 특정 타입
IntList = tuple[int, ...]                     # 가변 길이, 모두 int
Optional 와 파이프 — None 처리·python
# 옛 스타일
from typing import Optional, Union
def old(x: Optional[int]) -> Union[str, None]:
    if x is None:
        return None
    return str(x)

# 현대 (3.10+)
def modern(x: int | None) -> str | None:
    if x is None:
        return None
    return str(x)

# 디폴트 값 패턴 — None 의 가장 흔한 사용
def fetch(key: str, default: str | None = None) -> str | None:
    return {"a": "alpha"}.get(key, default)
Any vs object — 어느 거 언제·python
from typing import Any

def accept_anything(x: Any) -> int:
    # 타입 체커가 x 에 *어떤* 연산도 허용
    return x.completely_made_up_method()      # mypy: OK

def accept_object(x: object) -> int:
    # 타입 체커가 속성 접근 전 narrow 요구
    if isinstance(x, str):
        return len(x)
    raise TypeError

# Any 사용 — 타입 없는 라이브러리, 진짜 동적 데이터, gradual typing.
# object 사용 — '어떤 객체', 나중에 isinstance 로 narrow 할 때.
Alias — 복잡한 타입 명명·python
# 타입 alias 가 복잡한 타입에 한 번 이름 붙이게
from typing import Callable

UserId = int
UserData = dict[str, str | int | None]
Callback = Callable[[str, int], bool]

def process_user(uid: UserId, data: UserData, on_done: Callback) -> None:
    if on_done("start", uid):
        print("processed", data)

# 3.12+ 명시적 type 문
# type UserId = int    — TypeAlias 로 인식
# 더 자세한 건 lesson 5.

External links

Exercise

함수 top_n(items: list[dict[str, int]], n: int = 3, key: str = 'score') -> list[dict[str, int]] 작성 — key 내림차순으로 top-n 항목 반환. 곳곳에 적절한 타입 힌트. dict 셋 list ('score' 키 가진) 넘겨 테스트. 그 다음 일부러 list 대신 int 로 호출 — 작동하지만 mypy 가 표시하는 거 관찰.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.