같은 CLI 를 Rust·C++·Python 으로 만들어 보고 Rust 를 고른 이유

세션 사용량 게이지의 계산부만 떼어 세 언어로 같은 사양을 구현했습니다. 코드 길이, 빌드, 실행파일, 처리 속도를 같은 조건에서 재고 비교했습니다.

구독 사용량을 트레이에서 보여 주는 개인 프로젝트(SessionMeter)를 만들면서, 계산부를 어떤 언어로 두는 게 나은지 확인하고 싶었습니다. 감으로 정하지 않으려고 같은 사양의 CLI 를 Rust·C++·Python 으로 각각 구현하고 같은 기계에서 쟀습니다.

무엇을 만들었나

사용량 스냅샷 JSON 을 읽어 제공자별로 최근 사용률·평균·최댓값을 집계하고, 남은 시간과 함께 텍스트 게이지로 그리는 CLI 입니다. JSON 파싱, 날짜 계산, 집계, 문자열 렌더링이 한 번씩 들어가 실제 코드와 성격이 비슷합니다.

$ gauge usage.json
antigravity [############............]  51.8%  reset 3h 12m
claude      [##################......]  74.0%  reset 0h 48m
codex       [###############.........]  61.7%  reset 5h 03m
  • 세 구현의 출력은 바이트 단위로 같습니다(--json 출력으로 대조).
  • 각 언어에서 가장 흔한 선택지를 썼습니다. Rust 는 serde_json, C++ 는 단일 헤더 nlohmann/json, Python 은 표준 라이브러리 json 입니다.
  • 최적화 빌드로 쟀습니다. Rust --release, C++ /O2 /MT(MSVC), Python 은 PyInstaller onefile 로 실행파일까지 만들었습니다.
  • 벤치 입력은 20만 스냅샷, 16MB 짜리 단일 JSON 이고 3회 중 최소값을 취했습니다.

처리 속도

20만 스냅샷 처리 시간 막대 차트. Rust 104ms, C++ 534ms, Python 스크립트 990ms, Python 실행파일 1510ms.
같은 입력·같은 출력에서 Rust 104ms, C++ 534ms, Python 990ms

Rust 가 C++ 보다 5배 빠른 것은 언어의 한계 성능 차이가 아니라 기본으로 고르게 되는 라이브러리 차이입니다. serde 는 JSON 을 구조체로 곧장 역직렬화하지만, nlohmann/json 은 먼저 범용 DOM 트리를 만듭니다. C++ 에서도 simdjson 같은 선택지를 쓰면 좁힐 수 있습니다. 다만 그 선택은 직접 찾아서 붙여야 합니다.

배포 산출물

산출물 크기 막대 차트. Rust 257KB, C++ 389KB, Python onefile 9244KB.
Rust 257KB · C++ 389KB · Python onefile 9.0MB

Rust 와 C++ 는 실행파일 하나로 끝납니다(C++ 는 /MT 로 런타임을 정적 링크). Python 은 인터프리터를 통째로 넣어 9MB 가 되고, 실행할 때마다 압축을 풀어 임시 폴더에 펼치는 비용이 시작 시간에 더해집니다.

빌드

빌드 시간 막대 차트. Rust 클린 5.48초, Rust 재빌드 0.71초, C++ 2.02초, Python 패키징 15.38초.
한 줄 고치고 다시 빌드하는 데 걸리는 시간이 실제 개발 체감을 가른다

클린 빌드만 보면 C++(2.02초)가 Rust(5.48초)보다 빠릅니다. Rust 는 의존성까지 처음부터 컴파일하기 때문입니다. 그런데 개발 중에 반복되는 것은 한 줄 고치고 다시 빌드하기이고, 여기서는 Rust 가 0.71초로 앞섭니다. C++ 쪽은 단일 번역 단위라 매번 920KB 헤더를 다시 컴파일합니다.

코드 길이

코드 줄 수 막대 차트. Python 99줄, C++ 153줄, Rust 157줄.
줄 수만 보면 Python 이 가장 짧고 Rust 와 C++ 는 비슷하다

Rust 가 C++ 보다 4줄 깁니다. 대신 Rust 쪽 157줄에는 에러 처리가 전부 들어 있습니다. 파일 읽기 실패, JSON 형식 오류, 날짜 형식 오류가 모두 타입으로 드러나 컴파일러가 처리하라고 요구합니다. C++ 구현에서는 예외 처리와 반환값 검사를 제가 기억해서 넣어야 했고, 빠뜨려도 컴파일은 통과합니다.

전체 측정값 표 펼치기
항목RustC++ (MSVC)Python
코드 줄 수(빈 줄 제외)15715399
의존성 확보Cargo.toml 두 줄헤더 920KB 직접 내려받아 저장소에 포함없음(표준 라이브러리)
클린 빌드5.48초2.02초15.38초(PyInstaller)
재빌드(1줄 수정)0.71초2.0초(전체 재컴파일)없음
실행파일257KB389KB9,244KB
빌드 중간 산출물49MB(target/)수 MB(.obj)13MB(build/)
20만 스냅샷 처리104ms534ms990ms(스크립트) / 1,510ms(실행파일)
시작 시간(작은 입력)51ms49ms115ms
메모리 안전컴파일 타임 보장직접 관리런타임(GC)

그래서 Rust 를 권합니다

세 언어 모두 이 CLI 를 만들 수 있습니다. 그래도 이런 성격의 도구(오래 켜 두고, 배포해서 남에게 주고, 데이터가 커질 수 있는 것)라면 Rust 를 권합니다. 이유는 속도 하나가 아닙니다.

  1. 배포가 끝난다: 257KB 실행파일 하나. 런타임 설치도, 버전 충돌도 없습니다.
  2. 빠른 쪽이 기본값이다: 가장 흔한 선택지(serde)가 이미 빠릅니다. C++ 에서 같은 속도를 내려면 라이브러리를 따로 찾아 붙여야 합니다.
  3. 고치는 속도가 빠르다: 반복되는 재빌드가 1초 아래라 흐름이 끊기지 않습니다.
  4. 빠뜨린 처리를 컴파일러가 잡는다: 실패할 수 있는 지점이 타입에 드러나서, 급하게 짜도 최소한의 처리를 강제받습니다.
  5. 의존성 관리가 언어에 붙어 있다: 두 줄로 끝나는 일을, C++ 에서는 헤더를 내려받아 저장소에 넣는 것으로 해결해야 했습니다.

반대 방향도 분명합니다. 한 번 쓰고 버릴 분석 스크립트라면 Python 이 맞습니다. 99줄로 끝나고 빌드가 아예 없습니다. 기존 C++ 자산과 붙어야 하거나 특정 SDK 가 C++ 만 지원한다면 C++ 가 맞습니다. 이 비교는 '배포되는 작은 도구'라는 조건에서의 결론입니다.

측정 환경: Windows 11, rustc 1.98.1, MSVC 14.51, Python 3.14.6. 같은 기계에서 연달아 측정했고 절대값보다 상대 비교로 읽어야 합니다.