Skip to content

Latest commit

 

History

History
136 lines (103 loc) · 17.2 KB

report.md

File metadata and controls

136 lines (103 loc) · 17.2 KB

EXP-002 결과 보고: Java·PHP·C# RealWorld 백엔드 Ralph 루프

  • 실험일: 2026-10-19 (KST). 본 run 07:21-10:43(08:25-08:55 하네스 결함으로 중단), 후속 과제 10:43-11:16, 런타임 측정 11:38-15:32
  • 가설: L-02 — 같은 RealWorld 백엔드 과제에서 바이브 코딩 적합성(만드는 과정 지표와 결과물 지표의 종합 점수)은 Java, PHP, C# 사이에 차이가 있으며, 세 언어 안의 순위는 Sonnet 5.5와 Opus 5.5에서 같다.
  • 클라이언트: Claude Code 2.1.302
  • 판정: 검증(탐색) — C#이 두 모델 모두에서 종합 점수 1위였고(Sonnet 0.846, Opus 0.983) 2위와의 반복별 범위가 겹치지 않았다. 다만 2·3위(Java·PHP)는 모델마다 순서가 바뀌었고 범위가 겹쳐 구별되지 않으며, 18 run 모두 합격해 합격률로는 언어를 구별하지 못했다. 과제 하나·셀당 3회의 탐색 결과이므로 언어 선택의 참고 자료로만 쓴다.

해석 범위: 이 판정은 RealWorld 백엔드 과제 하나를 언어·모델 조합마다 3회 실행한 탐색 결과다. "검증"은 사전에 정한 판정 규칙의 조건을 충족했다는 뜻일 뿐이며, C#이 일반적으로 바이브 코딩 백엔드에 가장 적합하다는 증명이 아니다. 다른 과제·스택·버전·가중치에서는 순위가 달라질 수 있으므로 언어 선택의 간단한 참고 자료로만 읽는다.

실험 품질 규칙을 적용한다. 설계와 사전 기준은 README, 원자료는 runs/, 설계 이탈은 runs/deviations.md에 있다. 이 실험은 EXP-001과 실행 시점이 하루 다르다. 세 언어 안의 비교가 판정 근거이고, EXP-001 다섯 언어와 합친 8개 언어 순위는 EXP-001과 다른 시점의 탐색적 비교다.

사전 기준 대조

사전 등록 판정 규칙(README "주 지표와 사전 판정 기준")은 세 언어(Java, PHP, C#)만 비교 대상으로 둔 대시보드 종합 점수의 언어별 순위를 주 지표로 둔다. 종합 점수는 24개 지표를 같은 무게로 더하고, 세 언어 사이에서 값이 모두 같은 지표(상수 지표)는 뺀다. Sonnet에서는 pass_rate·iterations·followup_pass가, Opus에서는 여기에 error_rate·soak_error_rate가 상수였다. interventions는 기록하지 않은 빈 칸이라 점수에 들어가지 않는다. run 간 범위는 반복 번호(1·2·3)별로 그 반복의 run만으로 종합 점수를 다시 계산한 세 값의 최솟값-최댓값이다(EXP-001과 같은 방법). 반복별로 다시 정규화하므로 전체 점수가 반복별 범위 밖에 놓일 수 있다.

모델 1위 (점수, 반복별 범위) 2위 3위
Sonnet 5.5 C# 0.846 (0.772-0.925) Java 0.464 (0.433-0.494) PHP 0.366 (0.337-0.477)
Opus 5.5 C# 0.983 (0.911-0.975) PHP 0.419 (0.343-0.498) Java 0.319 (0.315-0.449)
사전 기준 관측 충족 여부
(1) 같은 언어가 두 모델 모두 1위, 2위와 범위 비중첩 C#이 두 모델 모두 1위. C#의 반복별 최솟값(Sonnet 0.772, Opus 0.911)이 2위의 최댓값(0.494, 0.498)보다 높다 충족 → 지지(탐색)
(2) 1위가 다르거나 범위가 겹침 → 부분 지지/보류 1위는 같다. 2·3위는 모델마다 순서가 바뀌었고(Sonnet Java>PHP, Opus PHP>Java) 두 모델 모두 범위가 겹친다 2·3위 순서는 구별되지 않음
(3) 합격률 0인 언어 별도 표기 해당 없음. 본 과제 18/18, 후속 과제 18/18 합격 —

사전 규칙은 1위만으로 지지 여부를 정하므로 판정은 "검증(탐색)"이다. 가설 문장의 "세 언어 안의 순위가 같다"는 1위에 대해서만 성립하고, 2·3위는 n=3에서 구별되지 않는다. 민감도 확인으로 상수 지표를 빼지 않고(EXP-001 보고서의 계산 방식) 다시 계산해도 C#이 1위(Sonnet 0.866, Opus 0.987)이고 2위와 범위가 겹치지 않았다.

run별 결과

본 과제 18 run(3 언어 × 2 모델 × 3회)과 후속 과제 18 run을 실행했다. 모든 run은 사람 개입 없이 끝났고 구독 한도 보류·변조 감지·비용 상한 도달은 없었다. PHP 2 run은 하네스 채점 결함으로 무효 처리하고 결함을 고친 뒤 처음부터 다시 실행했다(아래 "한계와 교란 변수"). 비용은 API 정가 환산 추정이며 실제 청구는 구독이다. 런타임 지표는 AWS Fargate Spot(Graviton4)에서 측정했다. rps·p95는 30초 부하 3회의 중앙값이다.

run 합격(iter) 구현 시간(분) 비용 추정(USD) 토큰 대리(K) rps p95(ms) 유휴/피크 메모리(MiB) 콜드 스타트(ms) 취약점 후속 과제
opus55-csharp-1 1(1) 6.4 1.27 104.3 2068 28.5 45.3/148.6 920 22 합격 2.1분
opus55-csharp-2 1(1) 6.5 1.47 112.2 2717 24.0 44.9/109.1 983 22 합격 1.8분
opus55-csharp-3 1(1) 6.2 1.40 112.6 1492 34.8 44.5/104.0 956 22 합격 1.9분
sonnet55-csharp-1 1(1) 3.4 0.50 75.6 1717 31.6 46.0/112.4 947 22 합격 1.4분
sonnet55-csharp-2 1(1) 3.7 0.53 84.1 2172 54.4 43.8/172.5 922 22 합격 1.1분
sonnet55-csharp-3 1(1) 3.6 0.53 84.1 1195 152.7 45.4/136.4 869 22 합격 1.5분
opus55-java-1 1(1) 15.1 2.28 153.1 1727 26.0 266.4/462.0 5242 69 합격 2.5분
opus55-java-2 1(1) 8.9 1.36 108.3 1534 27.0 216.6/296.4 5964 69 합격 2.5분
opus55-java-3 1(1) 11.1 2.10 149.3 2790 19.0 263.8/393.7 4227 69 합격 2.9분
sonnet55-java-1 1(1) 5.9 0.86 103.0 1383 26.6 210.5/304.5 5005 69 합격 1.2분
sonnet55-java-2 1(1) 9.3 0.79 110.8 2588 25.0 208.8/326.1 5975 69 합격 1.5분
sonnet55-java-3 1(1) 4.3 0.62 94.6 1582 33.4 208.5/317.5 4555 69 합격 1.4분
opus55-php-1 1(1) 8.3 1.37 85.9 562 73.3 92.7/117.5 1204 1606 합격 2.4분
opus55-php-2 1(1) 12.6 1.82 128.7 555 73.9 96.8/111.6 912 1606 합격 1.9분
opus55-php-3 1(1) 9.8 1.70 125.6 538 75.8 83.9/99.0 908 1606 합격 2.0분
sonnet55-php-1 1(1) 6.4 0.85 90.3 565 73.0 115.0/126.5 1546 1606 합격 1.2분
sonnet55-php-2 1(1) 8.2 1.00 103.0 499 82.7 87.3/112.9 663 1606 합격 1.2분
sonnet55-php-3 1(1) 9.2 0.82 88.5 461 87.6 85.3/102.3 708 1606 합격 1.5분

모델 유지·루프 기여

  • 요청/실제 모델 ID: 세션 jsonl의 assistant 메시지(message.id 중복 제거, 서브에이전트 포함) 모델이 Sonnet 조건 310건 전부 claude-sonnet-5-5, Opus 조건 436건 전부 claude-opus-5-5였다. fallback은 관측되지 않았다.
  • 첫 iteration 합격 18/18(본 과제), 18/18(후속 과제). 이 과제에서 Ralph 루프의 반복이 결과를 바꾼 경우는 없다.
  • 구독 한도·미실행 run: 없음. 오염 검사(R24)는 본 18 run과 후속 18 run 모두 하네스 경로 참조 0건이었다(runs/contamination.txt). 독립 재검증은 18 run × (호스트 2회 + Docker 2회) 72회 모두 13,154였다(runs/recheck.csv).

조건별 비교

지표 Sonnet 5.5 Opus 5.5 차이·한계
과제 수 / 과제별 반복 수 1 과제 × 3 언어 × 3회 같음 언어별 n=3
예산 내 합격 / 전체 9/9 9/9 천장 효과
합격률의 불확실성 9/9의 95% Clopper-Pearson 하한 약 66% 같음 과제 하나에서의 값
전체 비용 추정(본 과제) $6.51 $14.76 API 정가 환산, 실제 청구 아님
합격 한 건당 비용(언어별) C# $0.52, Java $0.76, PHP $0.89 C# $1.38, PHP $1.63, Java $1.91 두 모델 모두 C#이 가장 쌈
구현 시간 중앙값(최소-최대) 5.9분(3.4-9.3) 8.9분(6.2-15.1) Opus가 약 1.5배 느림
후속 과제 합격 9/9 9/9
사람의 검토·수정 시간 0 0 개입 없음
독립 품질 평가 Hurl 154 요청(고정 정본) + 후속 Hurl 167 요청 같음 숨긴 테스트 없음

언어별로는 두 모델에 공통인 경향이 뚜렷했다. C#은 구현 시간(중앙값 Sonnet 3.6분, Opus 6.4분)과 비용이 가장 작았고, 유휴 메모리(약 45 MiB), 이미지 크기(428 MB), 의존성 수(1-2개), 코드량(547·749줄)도 세 언어 중 가장 작았다. 처리량은 Java와 비슷한 상위였다(중앙값 1717·2068 rps). Java는 처리량은 C#과 비슷했지만(1582·1727 rps) 유휴 메모리(209·264 MiB), soak 중 메모리 증가(158·225 MiB), 콜드 스타트(약 5초), 빌드 시간(약 40초)이 가장 나빴다. PHP는 처리량이 가장 낮고(499·555 rps) p95가 가장 길었다(83·74 ms). 메모리 증가는 거의 없었다(1 MiB 미만). PHP의 취약점 1606건은 앱 의존성이 아니라 베이스 이미지(dunglas/frankenphp, Debian 13.7)의 OS 패키지에서 나왔다(Trivy 2333 ID, composer audit 0건). Java 69건 중 언어 스캐너(osv-scanner)가 찾은 Spring 의존성 ID는 17개이고 나머지는 이미지(Ubuntu 26.04, JRE)에서 나왔다. C# 22건은 모두 이미지(Ubuntu 24.04)에서 나왔다.

8개 언어 탐색적 비교 (판정에 쓰지 않음)

EXP-001 다섯 언어와 합쳐 같은 방법(상수 지표 제외)으로 다시 계산한 순위다. 실행일이 하루 다르고 하네스 스크립트·툴체인·Spot 용량이 다르므로(아래 "EXP-001 대비 버전 차이") 같은 조건의 순위로 읽으면 안 된다. 새 언어가 들어오면 정규화 범위가 바뀌어 EXP-001 다섯 언어의 표시 점수와 순위도 바뀐다. EXP-001 판정은 EXP-001 보고서가 기준이다.

모델 1 2 3 4 5 6 7 8
Sonnet 5.5 C# 0.840 Rust 0.824 Go 0.815 TypeScript 0.729 Python 0.712 C++ 0.621 Java 0.602 PHP 0.467
Opus 5.5 C# 0.848 Go 0.753 C++ 0.656 Rust 0.652 Python 0.603 TypeScript 0.588 PHP 0.511 Java 0.453

Sonnet에서 C#·Rust·Go의 반복별 범위(0.774-0.891, 0.763-0.841, 0.786-0.814)는 서로 겹친다. Opus에서는 C#의 반복별 최솟값(0.818)이 2위 Go의 최댓값(0.796)보다 높다.

EXP-001 대비 버전 차이

항목 EXP-001 EXP-002 비고
실행일 2026-10-18 2026-10-19 하루 차이
Claude Code 2.1.302 2.1.302 같음
모델 ID claude-sonnet-5-5, claude-opus-5-5 같음 서비스 측 모델 갱신 여부는 관측 불가
프롬프트 템플릿·채점 정본·k6 기준 커밋 변경 없음 자산 해시 목록 checksums.md5 md5 9350e00830befa80ffa2c0e33ede32f7(EXP-002 세 PROMPT 줄 추가)
하네스 스크립트 레지스트리 전환 전 레지스트리 전환 후(84ec1e0) + 실행 중 수정 2건(ee7f76b 채점 포트, b912806 C# 스캐너) 기존 언어 측정 동작은 회귀 테스트로 동일 확인
런타임 측정 Fargate Spot Graviton4, 앱 2 vCPU·1 GiB 같음 Spot 용량은 다름(Graviton4 확보 실패 2건 재측정)
언어 툴체인 해당 없음(다른 언어) OpenJDK 25.0.4.1, Maven 3.9.9, PHP 8.5.11, Composer 2.10.3, FrankenPHP 1.13.1, .NET SDK 10.0.108 runs/toolchain.txt
스캐너 pip-audit·govulncheck·cargo-audit·npm audit Java osv-scanner 2.7.0(Maven CycloneDX SBOM), PHP composer audit, C# dotnet list package --vulnerable 언어 간 취약점 수 직접 비교에 한계

usage·집계 검증

진단 지표 Sonnet 5.5 Opus 5.5
assistant 메시지 수(본+후속, 서브에이전트 포함) 310 436
토큰 대리지표 중앙값(본 과제) 90.3K 112.6K
후속 과제 토큰 대리지표 합 337.8K 396.0K
  • 원자료: run별 Claude Code 세션 jsonl(runs/sessions/, 서브에이전트 포함). 토큰 대리지표는 input + output + cache_creation이며 message.id로 중복을 제거했다(scripts/aggregate_tokens.py --recursive, R21). 무효 처리한 PHP 2 run의 세션은 runs/invalid/portbug/에 따로 두고 집계에 넣지 않았다.
  • 비용 산정: EXP-001과 같은 API 공개 단가 환산이다. 캐시 쓰기는 5분 TTL 단가로 계산하므로 1시간 TTL 사용분은 과소 계산된다. 비용 가드의 실험 누적 추정(Phase 0·무효 run·본·후속 포함)은 $24.72다.
  • 시간 범위: wall_min은 driver 시작부터 합격 게이트까지이며 채점 시간을 포함한다. 무효 처리 후 다시 실행한 PHP 2 run은 재실행 구간만 센다(driver.log의 held: 표시, R19).
  • 재현 자료: runs/phase0.md(툴체인·버전·파일럿), runs/bench.env, runs/run-order.txt, runs/harness/(실행 시 하네스·레지스트리 사본), 앱 소스(runs/apps/<run>/), Fargate 결과(runs/runtime/<run>/, 원본 runs/fargate/raw/<run>/).

관측과 설명

  • 직접 관측한 사실: 세 언어 모두 두 모델에서 첫 시도에 완주했다. 언어 차이는 완주 여부가 아니라 구현 시간·비용과 결과물의 런타임 특성(메모리, 콜드 스타트, 처리량, 이미지)에서 나타났고, C#은 과정 지표와 결과물 지표 대부분에서 동시에 앞섰다.
  • 가능한 설명: C#이 과정과 결과물 양쪽에서 앞선 것은 ASP.NET Core 최소 API·EF Core 조합의 보일러플레이트가 작고(코드량·의존성 최소), .NET 런타임이 JVM보다 유휴 메모리·콜드 스타트가 작기 때문일 수 있다. Java의 낮은 점수는 JVM 특성(메모리, 콜드 스타트, 빌드 시간)이 결과물 지표 여러 개에 함께 반영된 결과다. PHP는 요청 처리 모델(Octane 워커 + FrankenPHP)에서 처리량이 낮고, 지정 스택의 공식 이미지가 큰 Debian 기반이라 취약점·이미지 지표가 나빴다. 이 설명들은 언어와 지정 스택·에이전트가 고른 베이스 이미지를 분리하지 못한다.
  • 확인에 필요한 비교: 같은 언어 안에서 스택·베이스 이미지를 바꾼 비교, 가중치 민감도 분석(대시보드에서 가능), 더 어려운 과제(합격률 천장 해소).

한계와 교란 변수

  • 표본·과제 범위: 과제 하나, 언어×모델 셀마다 3회다. 18/18 합격은 이 과제에서의 관측이며 일반적인 높은 성공률을 뜻하지 않는다.
  • PHP 채점 포트 결함(재실행): FrankenPHP(Laravel Octane)는 앱 포트와 함께 관리 포트를 열고, measure.sh가 lsof의 첫 포트(관리 포트)로 채점해 모든 요청이 404였다. sonnet55-php-1(40분 상한 소진)과 진행 중이던 opus55-php-1을 무효로 하고, 채점이 주입한 PORT를 우선 쓰도록 고친 뒤 두 run을 iteration 1부터 다시 실행했다. 결함은 PHP 전체에 같게 작용했고 결과를 보고 고른 재실행이 아니므로 선택 편향은 없다고 판단한다. 무효 run의 앱도 고친 채점으로는 13,154였다.
  • C# 스캐너 결함(측정 전 수정): C# 앱 6개가 모두 .csproj를 하위 디렉터리에 두어 dotnet list package가 프로젝트를 찾지 못했다. 스캐너가 하위 프로젝트를 찾고 restore하도록 고치고, 알려진 취약 패키지로 탐지를 확인한 뒤 측정했다. 에이전트 run과 채점에는 영향이 없다.
  • Fargate 인프라 실패: opus55-csharp-2(ECR pull 시간 초과, Graviton4 미확보)와 opus55-php-3(Graviton4 미확보)가 측정값 없이 끝나 같은 사양으로 다시 측정했다. 18/18 Graviton4에서 측정했다.
  • 노출: claude-native는 비격리이며 실험자 글로벌 지침(~/.claude/CLAUDE.md), 사용자 스킬, MCP가 모든 조건에 같게 노출됐다.
  • 계측: cost_usd는 청구액이 아닌 대리지표다. 취약점 수는 Trivy 이미지 스캔(OS 패키지 포함)과 언어 스캐너의 합이고 언어마다 스캐너가 다르므로, 언어 간 차이는 주로 베이스 이미지 선택의 차이다. PHP의 trivy.json은 용량 때문에 trivy.json.gz로 보관했다.

정정 이력

최초 보고. 해당 없음.

결론 및 후속 실험

  • 결론: 이 RealWorld 과제에서 Java·PHP·C# 사이의 종합 점수 차이는 컸고, C#은 두 모델 모두에서 2위와 범위가 겹치지 않는 1위였다. C#은 구현이 가장 빠르고 쌌으며, 결과물도 메모리·이미지·의존성이 가장 작고 처리량은 상위였다. Java와 PHP의 순서는 모델마다 바뀌어 구별되지 않았다. 합격률은 세 언어 모두 100%로 천장에 닿았다. Opus 5.5는 Sonnet 5.5보다 비용이 약 2.3배, 시간이 약 1.5배였지만 합격률 이득은 없었다. EXP-001과 합친 탐색적 8개 언어 비교에서도 C#은 두 모델 모두 1위였으나, Sonnet에서는 Rust·Go와 범위가 겹친다.
  • 후속: 합격률 천장을 없앨 더 어려운 과제, 반복 수 확대, 같은 언어 안의 스택·베이스 이미지 변경 비교, 8개 언어를 같은 시점에 다시 실행하는 확인 실험.
  • 동기화: catalog·ROADMAP·4개 README·번역·대시보드는 이 보고와 같은 커밋 묶음에서 반영한다.