[Python] CLI 도구를 click 대신 typer로 만드는 이유
Python으로 CLI 도구를 만들다 보면 언젠가 한 번쯤 마주치는 고민이 있어. argparse는 너무 번거롭고, click은 익숙한데 데코레이터가 계속 쌓이다 보면 코드가 산으로 가는 느낌이랄까. 나도 예전엔 click이 사실상 표준인 줄 알고 별 의심 없이 썼는데, typer를 한 번 써보고 나니 다시 돌아가기가 쉽지 않더라고. 이 글에서는 그냥 신기술 추천하려는 게 아니라, CLI 프레임워크를 고를 때 뭘 기준으로 봐야 하는지, typer가 click보다 어떤 점에서 나은 선택이 될 수 있는지 우리끼리 차분하게 정리해보려 해.
물론 click이 갑자기 구려진 건 절대 아니야. 여전히 생태계도 크고 안정성도 검증됐고, 대규모 프로젝트에서도 충분히 버티고 있지. 하지만 도구 선택은 항상 맥락에 따라 달라지는 법이야. typer는 click 위에서 돌아가면서도 개발자 경험 측면에서 꽤 중요한 차이를 만들어내. 그리고 이 차이가 그냥 편리해서가 아니라, 유지보수나 협업, 장기적인 코드 건강에까지 영향을 준다는 게 핵심이야.
1. 타입 힌트가 곧 CLI 명세가 된다
click을 쓰다 보면 가장 지루하고 반복적인 게 파라미터 타입 일일이 선언하는 거야. Option이나 Argument 데코레이터 안에 type=click.INT 이렇게 계속 적어줘야 하잖아. 프로젝트가 커질수록 이 중복이 엄청 거슬려. 함수 시그니처에서 이미 int라고 해놨는데, CLI 레이어에서 똑같은 말을 또 해야 하는 구조라니까.
typer는 이 부분을 깔끔하게 해결해줘. Python 3.6 이상의 타입 힌트를 CLI 타입 시스템으로 그대로 가져다 쓰는 거지. 함수 파라미터에 annotation만 달아놓으면 typer가 알아서 적절한 변환과 검증을 처리해줘. int는 정수로, str은 문자열로, bool은 플래그로 알아서 해석되고. 개발자 입장에서는 그냥 평소에 함수 짜듯이 자연스럽게 코드 쓰면 되고, CLI용으로 타입을 중복 선언할 필요가 없어.
이건 단순히 코드가 짧아지는 문제가 아니야. 타입 힌트는 요즘 Python 코드베이스의 기본 중 기본이잖아. mypy나 pyright로 정적 검사 돌리고, IDE 자동완성이랑 타입 추론 믿으면서 개발하는 환경에서 typer는 기존 도구들이랑 자연스럽게 연결돼. 반면 click은 CLI 프레임워크만의 별도 타입 체계를 고집하다 보니 정적 분석 도구랑 괴리가 생길 수밖에 없어.
예시를 보면 감이 확 오거든. click에서는 type이랑 default를 데코레이터가 쥐고 있지만, typer에서는 함수 시그니처가 유일한 진실의 출처가 되는 거야. 구조적으로 훨씬 깔끔하고, 테스트 코드 짤 때도 함수 단위로 접근하기가 편하지. 테스트할 때 CLI 진입점이 아니라 순수 함수만 import 해서 검증하면 되니까 말이야.
# click 방식
import click
@click.command()
@click.option('--count', default=1, help='반복 횟수', type=int)
def hello(count):
for _ in range(count):
click.echo("Hello")
# typer 방식
import typer
def hello(count: int = 1):
for _ in range(count):
typer.echo("Hello")
app = typer.Typer()
app.command()(hello)
위 예시만 봐도 typer 쪽이 훨씬 읽기 쉽고 직관적이지 않아? 데코레이터 양이 줄어들면서 코드의 핵심 로직이 더 잘 보이게 돼. 작은 스크립트에서는 별 차이 없어 보일 수도 있는데, 서브커맨드가 열 개 이상 쌓이는 규모가 되면 이 가독성 차이가 꽤 크게 와닿을 거야.
2. 데코레이터 지옥에서 벗어나기
click으로 복잡한 CLI를 만들다 보면 함수 위에 데코레이터가 수직으로 쌓이는 광경을 자주 보게 돼. @click.command(), @click.option(...)이 다섯 개, @click.argument(...)까지 붙으면 함수 정의보다 데코레이터가 더 길어지는 기가 막힌 상황이 벌어지지. 이건 그냥 보기 싫은 문제를 넘어서 코드의 핵심을 파악하는 데도 방해가 돼.
typer는 이 데코레이터 중첩을 근본적으로 줄여줘. 앞서 말했듯이 타입 힌트와 기본값이 CLI 명세를 대신하니까, 굳이 데코레이터로 모든 걸 선언할 필요가 없는 거야. 옵션이 많아져도 함수 시그니처 안에서 해결되니까 코드가 훨씬 평평해지고 깔끔해져. 눈이 편안하다고 해야 하나, 그냥 숨통이 트이는 느낌이야.
특히 팀 프로젝트에서 이건 꽤 큰 장점이야. 데코레이터가 덜 쌓일수록 코드 리뷰할 때도 부담이 덜 하고, 처음 보는 사람도 함수 하나만 봐도 대충 어떤 CLI인지 파악하기가 쉬워. click에서는 데코레이터를 하나하나 뜯어봐야 파라미터 구조가 보이는데, typer에서는 함수 선언부만 봐도 끝나는 거거든. 협업 관점에서 이 차이는 생각보다 꽤 크지.
3. 예쁘고 친절한 자동 도움말
typer는 내부적으로 rich 라이브러리를 쓰는데, 이 덕분에 --help 출력이 기본적으로 예뻐. click의 기본 help는 기능적으로 문제없지만 솔직히 좀 촌스럽잖아. 반면 typer는 색상도 알아서 들어가고, 테이블도 예쁘게 정렬돼서 출력돼. 별도로 꾸미지 않아도 기본 상태가 이미 보기 좋아.
게다가 typer는 docstring도 알아서 잘 활용해. 함수에 써놓은 docstring이 명령 설명으로 자연스럽게 연결되고, 파라미터 설명도 힌트나 docstring에서 끌어다 쓸 수 있어. 문서화에 들이는 공이 확 줄어들어. click에서도 어느 정도 가능하지만 typer는 이게 더 매끄럽고 직관적이야. 작은 스크립트 하나 만드는데도 도움말 예쁘게 나오면 기분이 좋거든, 인정?
4. 쉘 자동완성은 덤이다
typer를 쓰면 쉘 자동완성 설정이 거의 공짜로 따라와. typer-cli를 설치하면 bash, zsh, fish용 자동완성 스크립트를 손쉽게 생성할 수 있어. click도 click-completion 같은 추가 패키지를 쓰면 되긴 하는데, typer는 이게 기본 생태계에 더 가깝게 녹아있어서 설정이 훨씬 간단하지.
CLI 도구를 팀원들이나 사용자들한테 배포할 때 탭 누르면 알아서 완성되는 경험은 생각보다 큰 만족도를 줘. 특히 옵션이나 서브커맨드가 많을수록 이건 그냥 필수에 가까워. typer는 이런 부분까지 개발자 경험의 연장선상에서 깔끔하게 챙겨주는 느낌이야.
5. 그래도 click이 필요할 때가 있다
여기까지 typer 장점만 말했는데, click을 무시할 순 없어. click은 수년간 쌓인 생태계가 어마어마하고, 이미 click 기반으로 짜놓은 대규모 코드베이스가 있다면 굳이 typer로 갈아탈 이유는 없지. 또 click만의 고급 기능들이나 세밀한 커스터마이징이 필요한 경우도 있고.
typer가 click을 완전히 대체하려는 게 아니라는 점도 중요해. typer는 사실 click 위에서 돌아가는 프레임워크야. 즉 typer가 막힌다 싶으면 언제든 click의 원시 기능을 꺼내 쓸 수 있어. 두 개가 적대 관계가 아니라 typer가 click을 더 현대적이고 파이썬다운 방식으로 포장한 거라고 보면 돼.
그러니까 새 프로젝트를 시작하거나 기존 CLI를 리팩토링할 때는 typer를 먼저 검토해보는 게 좋아. 반면 이미 click으로 잘 굴러가는 시스템이 있다면 "지금 당장" 옮길 필요는 없지. 선택은 항상 현재 맥락과 리소스를 보고 하는 게 맞아. 무조건 typer가 정답이라고 주장하려는 게 아니라, 이제는 typer도 충분히 성숙해서 진지한 후보가 됐다는 거야.
마무리
정리하자면, typer가 click보다 나은 지점은 크게 세 가지로 압축할 수 있어. 첫째, 타입 힌트로 중복 선언을 없앤다. 둘째, 데코레이터 중첩을 줄여서 코드를 깔끔하게 만든다. 셋째, 도움말과 자동완성 같은 주변 경험을 기본적으로 잘 챙긴다. 이 세 가지는 각각 작은 차이처럼 보이지만 모이면 개발자의 일상을 꽤 바꿔놔.
물론 익숙한 게 최고라는 사람도 있을 거고, 이미 click에 파묻혀서 잘 쓰고 있다면 굳이 바꿀 필요는 없어. 하지만 Python으로 CLI를 새로 만든다거나, 기존 코드가 점점 데코레이터에 질식하는 느낌이 든다면 이번에 typer 한 번 손대보는 것도 괜찮을 거야. 나도 그랬고.
오히려 와인 고를 때랑 비슷해. click은 검증된 클래식 와인 같고, typer는 요즘 기분 좋게 마시기 딱 좋은 모던 와인 같은 느낌이지. 둘 다 각자의 자리가 있고, 중요한 건 지금 내 상황에 어떤 게 더 잘 맞느냐는 거야. 오늘 글이 그 판단에 조금이나마 도움이 됐으면 좋겠네.