Claude Code로 13개 언어에서 간소화한 Git(미니-git)을 구현하게 하고 시간·비용·안정성을 비교한 정량 벤치마크. Ruby, Python, JavaScript가 가장 빠르고 저렴하며 안정적이었고, 정적 타입 언어는 1.4–2.6배 더 느리고 비쌌다.
Claude Code에게 13개 언어로 매우 단순화한 Git 버전을 구현하게 했습니다. Ruby, Python, JavaScript가 가장 빠르고, 가장 저렴하며, 가장 안정적이었습니다. 정적 타입 언어는 1.4–2.6× 더 느리고 더 비쌌습니다.
AI 코딩 에이전트에는 어떤 프로그래밍 언어가 가장 잘 맞을까요?
"정적 타이핑은 AI 환각 버그를 막아준다!"
"아니, 타입 애너테이션을 생략하면 토큰을 아낄 수 있어!"
정성적 논쟁은 많지만 정량 데이터는 드뭅니다. 그래서 실험을 해봤습니다.
Claude Code에게 “mini-git” — Git의 단순화 버전 — 을 여러 언어로 구현하게 하고, 각 언어에 대해 시간과 비용을 측정했습니다. Git은 유명하게도 Linus가 2주 만에 만들었기 때문에, 좋은 과제로 보였습니다.
과제는 두 단계로 나뉘었습니다:
init, add, commit, log 구현.status, diff, checkout, reset 추가.프롬프트는 단순히 다음과 같았습니다: "SPEC-v1.txt를 읽고 구현한 뒤, test-v1.sh가 통과하도록 하라." v2도 같은 방식이었습니다.
비교한 언어:
| Category | Languages |
|---|---|
| Dynamic | Python, Ruby, JavaScript, Perl, Lua |
| Dynamic + type checker | Python/mypy, Ruby/Steep |
| Static | TypeScript, Go, Rust, C, Java |
| Functional | Scheme (dynamic), OCaml (static), Haskell (static) |
Python/mypy는 mypy --strict로 검증되는, 완전히 타입 애너테이션이 달린 Python을 작성합니다. Ruby/Steep은 steep check로 검증되는 RBS 타입 시그니처를 작성합니다. 이를 통해 같은 언어 안에서 타입 체크 오버헤드를 직접 비교할 수 있습니다.
각 언어는 20번씩 실행했습니다. 모델은 Claude Opus 4.6 (high effort)였습니다.
20회 실험의 평균 결과(평균 비용 기준 정렬):
| Language | Tests passed (v1+v2) | Time (v1+v2) | Avg. cost | LOC (v2) |
|---|---|---|---|---|
| Ruby | 40/40 | 73.1s ± 4.2s | $0.36 | 219 |
| Python | 40/40 | 74.6s ± 4.5s | $0.38 | 235 |
| JavaScript | 40/40 | 81.1s ± 5.0s | $0.39 | 248 |
| Go | 40/40 | 101.6s ± 37.0s | $0.50 | 324 |
| Java | 40/40 | 115.4s ± 34.4s | $0.50 | 303 |
| Rust | 38/40 | 113.7s ± 54.8s | $0.54 | 303 |
| Perl | 40/40 | 130.2s ± 44.2s | $0.55 | 315 |
| Python/mypy | 40/40 | 125.3s ± 19.0s | $0.57 | 326 |
| OCaml | 40/40 | 128.1s ± 28.9s | $0.58 | 216 |
| Lua | 40/40 | 143.6s ± 43.0s | $0.58 | 398 |
| Scheme | 40/40 | 130.6s ± 39.9s | $0.60 | 310 |
| TypeScript | 40/40 | 133.0s ± 29.4s | $0.62 | 310 |
| C | 40/40 | 155.8s ± 40.9s | $0.74 | 517 |
| Haskell | 39/40 | 174.0s ± 44.2s | $0.74 | 224 |
| Ruby/Steep | 40/40 | 186.6s ± 69.7s | $0.84 | 304 |
600회 실행(15개 언어 × 2단계 × 20회) 중 실패(테스트 불통과)는 3회뿐이었습니다. 실패는 Rust(2)와 Haskell(1)이었습니다. Rust 실패 로그 중 하나에서 에이전트가 "테스트가 틀렸다"고 주장했습니다. 다른 Rust 실험들은 모두 성공했기 때문에, 이는 환각으로 보입니다.
총 시간(v1 + v2) 도트 플롯:
그리고 비용:
Ruby, Python, JavaScript가 상위 3개입니다: 73–81초, $0.36–0.39, 표준편차도 낮아 빠르고 안정적입니다.
4위부터(Go, Rust, Java)는 분산이 급격히 커집니다. Go의 평균은 102초지만 ±37초의 변동 폭이 있습니다.
시간과 비용은 강하게 상관됩니다:
v2 완료 후 LOC:
OCaml(216), Ruby(219), Haskell(224)이 가장 간결합니다. C는 517줄로 두드러집니다.
흥미롭게도 LOC가 적다고 해서 생성이 더 빠르거나 더 저렴하다는 뜻은 아닙니다. OCaml과 Haskell은 간결하지만, 속도와 비용 효율은 중간~하위권인데, 생각 토큰(thinking token) 사용량이 높기 때문으로 보입니다.
단계별 세부 내역:
| Language | v1 Time | v1 Turns | v1 LOC | v1 Tests | v2 Time | v2 Turns | v2 LOC | v2 Tests | Total Time | Avg. Cost |
|---|---|---|---|---|---|---|---|---|---|---|
| Ruby | 33.2s± 2.5s | 6.0 | 107 | 20/20 | 40.0s± 3.0s | 7.0 | 219 | 20/20 | 73.1s± 4.2s | $0.36 |
| Python | 32.9s± 1.3s | 6.0 | 113 | 20/20 | 41.8s± 4.5s | 7.1 | 235 | 20/20 | 74.6s± 4.5s | $0.38 |
| JavaScript | 36.0s± 3.5s | 6.0 | 123 | 20/20 | 45.1s± 4.1s | 7.2 | 248 | 20/20 | 81.1s± 5.0s | $0.39 |
| Go | 47.5s±34.5s | 7.7 | 143 | 20/20 | 54.1s±12.3s | 9.7 | 324 | 20/20 | 101.6s±37.0s | $0.50 |
| Java | 64.3s±31.1s | 8.7 | 152 | 20/20 | 51.2s± 8.1s | 9.6 | 303 | 20/20 | 115.4s±34.4s | $0.50 |
| Rust | 53.6s±36.7s | 9.4 | 139 | 19/20 | 60.1s±19.2s | 10.1 | 303 | 19/20 | 113.7s±54.8s | $0.54 |
| Perl | 84.4s±43.1s | 9.2 | 173 | 20/20 | 45.7s± 6.8s | 7.5 | 315 | 20/20 | 130.2s±44.2s | $0.55 |
| Python/mypy | 52.7s± 8.3s | 9.2 | 171 | 20/20 | 72.6s±14.4s | 12.2 | 326 | 20/20 | 125.3s±19.0s | $0.57 |
| OCaml | 80.9s±28.8s | 11.2 | 111 | 20/20 | 47.1s± 6.0s | 9.2 | 216 | 20/20 | 128.1s±28.9s | $0.58 |
| Lua | 96.4s±42.8s | 10.1 | 226 | 20/20 | 47.2s± 5.2s | 8.1 | 398 | 20/20 | 143.6s±43.0s | $0.58 |
| Scheme | 66.7s±36.7s | 8.9 | 171 | 20/20 | 63.9s±10.0s | 10.6 | 310 | 20/20 | 130.6s±39.9s | $0.60 |
| TypeScript | 69.9s±18.8s | 12.2 | 149 | 20/20 | 63.1s±17.8s | 11.3 | 310 | 20/20 | 133.0s±29.4s | $0.62 |
| C | 65.0s±18.2s | 8.2 | 276 | 20/20 | 90.8s±39.1s | 13.7 | 517 | 20/20 | 155.8s±40.9s | $0.74 |
| Haskell | 74.3s±39.1s | 10.3 | 119 | 19/20 | 99.6s±32.4s | 16.4 | 224 | 20/20 | 174.0s±44.2s | $0.74 |
| Ruby/Steep | 105.0s±65.2s | 20.2 | 150 | 20/20 | 81.6s± 8.8s | 17.2 | 304 | 20/20 | 186.6s±69.7s | $0.84 |
"Turns"는 단일 프롬프트 실행 안에서의 API 왕복(tool call → result → 다음 응답) 횟수입니다.
v1에서 언어 간 격차가 가장 크게 나타납니다. Python(32.9초)과 Ruby(33.2초)가 선두이고, 그 뒤를 JavaScript(36.0초)가 잇습니다. Ruby/Steep은 105.0초로 — 일반 Ruby보다 3.2× 느립니다. Lua(96.4초)와 OCaml(80.9초)도 느립니다.
v1은 빈 디렉터리에서 시작하므로, 프로젝트 설정 파일(Cargo.toml, package.json 등)이 필요한 언어는 추가 오버헤드가 발생합니다. Python, Ruby, JavaScript는 minigit 파일 하나만 생성하면 되며, 이것이 격차를 부분적으로 설명할 수 있습니다.
v2에서는 격차가 줄어듭니다. 상위 3개는 그대로 Ruby(40.0초), Python(41.8초), JavaScript(45.1초)입니다. Perl(45.7초), OCaml(47.1초), Lua(47.2초)가 근소한 차이로 뒤따릅니다.
Haskell은 v2에서도 가장 느리며, LOC가 가장 적음(224)에도 평균 99.6초가 걸립니다 — 생각 토큰에 큰 비용을 쓰는 것으로 보입니다. C는 LOC가 매우 많음(517) 때문에 90.8초가 걸립니다.
타입 체커 오버헤드: Python/mypy는 Python보다 1.6–1.7× 느리고, Ruby/Steep은 Ruby보다 2.0–3.2× 느립니다.
실험 코드와 결과는 모두 GitHub에서 확인할 수 있습니다:
Claude Code가 13개 프로그래밍 언어에서 코드를 얼마나 효율적으로 생성하는지 비교하는 정량 벤치마크입니다.
자세한 논의는 블로그 글을 참고하세요: Which Programming Language Is Best for Claude Code? / 日本語版
적어도 프로토타이핑 규모의 작업에서는 Ruby, Python, JavaScript(TypeScript는 제외)가 Claude Code에 가장 잘 맞는 것으로 보입니다 — 가장 빠르고, 가장 저렴하며, 가장 안정적입니다.
"정적 타이핑은 AI 환각 버그를 막는다!" 대 "동적 타이핑은 토큰을 아낀다!" — 정성적 주장은 넘치지만, 정량 데이터는 드뭅니다. 이 실험은 그 격차를 메우는 것을 목표로 합니다.
Claude Code(Opus 4.6)에게 mini-git — Git의 단순화 버전 — 을 여러 프로그래밍 언어로 구현하게 하고, 언어별로 시간, 비용, 코드 라인 수를 측정했습니다.
과제는 두 단계로 나뉩니다:
init, add, commit, log 구현.실행별 결과는 report.md에 있습니다. 실행 로그와 생성된 소스 코드는 data branch에 있습니다.
참고: benchmark.rb는 --dangerously-skip-permissions를 사용합니다. 실험을 재현하고 싶다면 주의하세요(저는 Docker 안에서 실행했습니다).
이하 내용은 제 해석입니다. 저는 Ruby 커미터이므로, 그 편향을 염두에 두세요. 또한 생성된 코드를 모두 자세히 분석하지는 않았습니다.
이 실험만으로 단일 원인을 특정할 수는 없고, 저도 단일 원인이 있다고 생각하지 않습니다. 하지만 경향으로부터 가설을 세울 수는 있습니다:
아마도 이러한 요인들이 결합되어 관측된 결과를 만들었을 것입니다.
그럴 수도 있습니다. 테스트는 통과하지만, 동적 타입 언어에서는 테스트되지 않은 경로에 타입 오류가 있을 수 있습니다.
다만 타입 오류는 발견하고 수정하기 가장 쉬운 버그 중 하나입니다. 타입 체커 없이 에이전트가 타입 오류를 자주 만들어낸다면, 비슷한 비율로 로직 버그도 만들어낼 가능성이 높습니다 — 그러면 문제는 타입 체크를 넘어섭니다.
또한 600회 중 실패 3회는 Rust(2)와 Haskell(1)에서만 발생했다는 점도 주목할 만합니다 — 둘 다 소유권이나 모나드 같은 고유 개념이 있는 정적 타입 언어입니다. 우연일 수도 있지만, 타입이 모든 버그를 막아주지는 않습니다.
저는 크다고 생각합니다.
현실의 개발에서는 계속 반복합니다: 프롬프트 → 대기 → 다음 작업을 생각 → 다시 프롬프트. 30초를 기다리는 것과 60초를 기다리는 것의 차이는 — 총 시간뿐 아니라 집중과 흐름 측면에서도 — 중요합니다. 반복적 개발에서는 응답 시간이 핵심입니다.
"더 견고한 것을 만들기 위해 더 오래 걸린다"는 주장은 합리적이지만, 경쟁자가 2배 속도로 출시하고 있다면 기다리는 것이 맞을까요? 개발 속도 자체도 품질의 한 차원입니다.
물론 장차 차이가 1초 vs 0.5초로 줄어든다면, 정말로 중요하지 않게 될 것입니다.
저도 동의하지 않는 것은 아닙니다. 다만 15개 언어에 대해 공정한 대규모 벤치마크를 설계하는 것은 상당히 어렵습니다. 누군가 시도해 보면 좋겠습니다.
전적으로 그렇습니다. 생성 관점에서도 마찬가지입니다 — 생태계를 활용할 수 있다면 생성해야 할 코드가 줄어들어 더 빠르고 더 저렴해질 것입니다. 또한 애플리케이션에서 런타임 속도가 중요하다면, 느린 동적 언어를 고를 이유가 없습니다.
이 실험에서는 언어 수준의 차이를 분리하기 위해 외부 라이브러리 의존성이 없는 과제를 의도적으로 선택했습니다. 스펙이 SHA-256 대신 커스텀 해시를 사용하는 것도 이 때문입니다.
Claude Code로 코드 생성에 가장 적합한 프로그래밍 언어가 무엇인지 정량적으로 평가했습니다. 적어도 프로토타이핑 규모의 작업에서는 Ruby, Python, JavaScript가 가장 잘 맞는 것으로 보입니다.
더 큰 규모에서는 정적 타이핑이 유리해질 수도 있습니다 — 누군가 이를 테스트해 보면 좋겠습니다.
고전적인 전략 — 동적 언어로 시작한 뒤 프로젝트가 성숙하면 정적 언어로 마이그레이션 — 이 여전히 올바른 선택일 수 있습니다. 코딩 에이전트는 언어 간 마이그레이션에도 매우 능숙해 보이며(검증 필요), 이는 점점 더 현실적인 옵션이 되고 있습니다.