typer (FastAPI 작가) 가 click 위에 앉아서 Python 타입 힌트로 인자 선언. def hello(name: str, count: int = 1) — name 이 positional 인자, count 가 옵션 --count. 타입 힌트가 모든 거 driving, 데코레이터에 반복 X. Pippa 의 CLI wrapper 가 typer.
ergonomic 승리
함수 시그니처 자체가 CLI 스펙. 타입 힌트, 디폴트, 타입 검증 다 거기서. 명시적 옵션엔 name: str = typer.Option(...). 더 풍부한 config 엔 name: Annotated[str, typer.Option()]. 결과 CLI 가 일반 Python 함수처럼 보이고, 모든 정적 타입 혜택.
서브커맨드 — click 보다 쉬움
app = typer.Typer(), 그 다음 @app.command() 로 함수 데코레이트. 각 함수가 자기 이름의 서브커맨드. 계층엔 app.add_typer(other_app, name="users") 로 sub-typer 중첩. 현대 Python 프로젝트가 새 CLI 에 click 보다 typer 자주 사용.
Rich 통합
typer 가 디폴트로 rich 라이브러리와 통합 — 색깔 출력, progress bar, 테이블, 포맷된 traceback. 일반 출력엔 typer.echo, 색깔엔 typer.secho, progress 엔 typer.progressbar. polish 가 노력 없이 광범위.
Pythonic Way: 2026 에 새 CLI 짜면 typer 디폴트. 타입-힌트 driven ergonomics 가 best-in-class. 0 의존성 중요할 때만 argparse, typer 의 추상화 안 맞을 때 click. 셋이 형제, 경쟁자 X — typer 가 안에서 click 사용.
Code
typer — 타입-힌트 driven·python
# pip install typer
import typer
app = typer.Typer()
@app.command()
def hello(name: str, count: int = 1, shout: bool = False):
"""NAME 한테 count 번 인사."""
msg = f"Hello, {name}!"
if shout:
msg = msg.upper()
for _ in range(count):
typer.echo(msg)
if __name__ == "__main__":
app()
# python tool.py alice --count 3 --shout
# HELLO, ALICE!
# HELLO, ALICE!
# HELLO, ALICE!
Typer 서브커맨드·python
import typer
app = typer.Typer()
@app.command()
def add(name: str):
"""사용자 추가."""
typer.echo(f"adding {name}")
@app.command()
def remove(name: str, force: bool = False):
"""사용자 제거."""
if not force:
confirmed = typer.confirm(f"{name} 제거?")
if not confirmed:
raise typer.Abort()
typer.echo(f"removed {name}")
if __name__ == "__main__":
app()
# python tool.py add alice
# python tool.py remove bob --force
더 풍부한 옵션 메타데이터엔 Annotated·python
from typing import Annotated
import typer
from pathlib import Path
app = typer.Typer()
@app.command()
def process(
input_path: Annotated[Path, typer.Argument(help="입력 파일 경로", exists=True)],
output_path: Annotated[Path, typer.Argument(help="출력 파일 경로")],
verbose: Annotated[bool, typer.Option("-v", "--verbose", help="verbose 출력")] = False,
workers: Annotated[int, typer.Option(min=1, max=64)] = 4,
):
"""입력을 N worker 로 출력 처리."""
typer.echo(f"input: {input_path}")
typer.echo(f"output: {output_path}")
typer.echo(f"workers: {workers}")
if verbose:
typer.echo("verbose 모드")
# 제약 (min/max/exists 등) 자동 체크
이전 lesson 의 click CLI 를 typer CLI 로 다시 짜. greet/farewell 서브커맨드, 같은 인자. 타입 힌트로 선언. 코드 길이와 명료성 비교. (보너스 — Annotated[int, typer.Option(min=1, max=100)] 사용 옵션 추가 + typer 가 범위 강제 확인.)
Progress
Progress is local-only — sign in to sync across devices.