AI를 활용한 Rust 개발 확장: 100K 라인 합의 엔진으로부터의 교훈

AI 지원 코딩의 약속은 종종 "vibe coding"의 열풍과 복잡한 시스템을 유지 관리해야 하는 현실 사이에서 요동칩니다. 하지만 분산 합의와 같은 엄격한 도메인에 적용될 때, AI는 단순한 자동 완성을 넘어 생산성의 주요 동력이 될 수 있습니다.

최근 한 프로젝트에서, 한 개발자는 Rust 기반의 multi-Paxos 합의 엔진을 구현함으로써 AI 코딩 에이전트의 한계를 테스트했습니다. 목표는 Azure의 Replicated State Library (RSL)를 현대화하는 것이었으며, 파이프라이닝 부족, Non-Volatile Memory (NVM) 지원 부재, RDMA에 대한 제한적인 하드웨어 인식과 같은 10년 된 한계점들을 해결하는 것이었습니다. 그 결과 생산성이 엄청나게 도약했습니다. 약 4주 만에 100K 라인의 Rust 코드가 작성되었으며, 이후 성능 튜닝을 통해 처리량이 초당 23K에서 300K 작업으로 향상되었습니다.

AI 기반 워크플로우

이 정도 규모의 결과물을 달성하기 위해서는 단일 도구 이상의 것이 필요했습니다. 개발자는 GitHub Copilot, Claude Code, Codex, Augment Code, Kiro, Trae를 포함한 에이전트 제품군을 활용했습니다. 현재 주요 동력은 Claude CodeCodex CLI이며, VS Code가 diff와 미세 조정을 위한 인터페이스 역할을 합니다.

한 가지 주목할 만한 관찰 결과는 CLI 중심의 흐름으로의 전환이었는데, 이는 비동기적 개발 사이클을 가능하게 합니다. AI를 주요 구현자로, 인간을 설계자로 취급함으로써, 개발자는 리더 선출(leader election), 로그 복제(log replication), 스냅샷 생성(snapshotting), 구성 변경(configuration changes)을 포함한 RSL의 전체 기능 세트를 전통적인 개발 시간의 아주 일부만 사용하여 구현할 수 있었습니다.

정확성 보장: AI를 위한, AI에 의한 코드 계약(Code Contracts)

Paxos와 같은 복잡한 프로토콜을 구현하는 것은 위험이 따릅니다. 단 하나의 논리적 오류가 치명적인 상태 불일치를 초래할 수 있기 때문입니다. 이를 방지하기 위해 프로젝트는 표준 유닛 테스트를 넘어 **코드 계약(code contracts)**을 채택했습니다.

코드 계약은 핵심 함수의 전제 조건, 사후 조건, 그리고 불변량을 정의합니다. 이 프로젝트에서 AI는 세 가지 뚜렷한 수준에서 활용되었습니다:

  1. 계약 생성: GPT-5 High 또는 Opus 4.1과 같은 고성능 모델을 사용하여 상세한 계약을 작성합니다. 예를 들어, Paxos 구현의 process_2a 메서드는 상태 전환이 유효한지 확인하기 위해 16개의 별도 계약을 사용합니다.
  2. 대상 테스트 생성: 계약이 수립되면, AI는 해당 계약의 사후 조건을 트리거하도록 설계된 특정 테스트 케이스를 생성합니다.
  3. 속성 기반 테스트(Property-Based Testing): AI는 이러한 계약을 속성 기반 테스트로 변환하며, 무작위 입력을 사용하여 상태 공간을 탐색하고 수동 테스트로는 놓칠 수 있는 엣지 케이스를 찾아냅니다.

이 접근 방식은 AI가 생성한 계약이, 자칫하면 심각한 복제 일관성 문제를 일으켰을 법한 미묘한 Paxos 안전성 위반 사항을 식별해냈을 때 그 가치를 증명했습니다.

경량 스펙 기반 개발 (SDD)

엄격한 SDD(요구사항 → 설계 → 작업 목록)는 유지 관리 부담이 될 수 있지만, 이 프로젝트는 spec kit을 사용하는 "경량" 버전을 채택했습니다.

워크플로우는 /specify를 통해 사용자 스토리와 수용 기준을 포함하는 스펙 마크다운을 생성하는 것으로 시작하며, 그 다음 /clarify를 사용하여 AI가 스스로 비판하고 누락된 시나리오를 제안하도록 합니다. 스펙이 정제되면, AI는 현재 AI 에이전트들에게 최적의 지점인 단일 사용자 스토리에 대한 계획을을 생성하고 구현을 실행합니다.

공격적인 성능 최적화

성능 튜닝은 작업의 반복적인 특성 덕분에 AI가 탁월한 능력을 발휘하는 분야입니다. 개발자는 처리량을 초당 23K에서 300K ops/sec로 높이기 위해 다음과 같은 긴밀한 루프를 따랐습니다:

  • 계측(Instrumentation): AI는 모든 코드 경로에 대해 지연 시간 메트릭을 계측합니다.
  • 분석(Analysis): AI는 Python 스크립트를 작성하여 트레이스 로그를 분석하고 분위수를 계산하여 병목 현상을 찾습니다.
  • 최적화(Optimization): AI는 할당을 최소화하고, zero-copy 기술을 적용하며, async 오버헤드를 줄이는 등의 변경 사항을 제안하고 구현합니다.
  • 검증(Validation): 다시 측정하고 반복합니다.

비판적 관점 및 반론

인상적인 수치에도 불구하고, 이 프로젝트는 AI 생성 코드의 본질에 대한 개발자 커뮤니티 내의 상당한 논쟁쟁을 불러일으켰습니다.

"AI Slop"에 대한 우려

몇몇 비판가들은 원래 RSL 라이브러리가 C++로 36K 라인이었다는 점을 지적했습니다. AI가 생성한 Rust 버전이 130K 라인에 달한다는 사실은 잠재적인 효율성 부족을 시사합니다. 한 댓글러는 다음과 같이 언급했습니다:

"Rust는 더 표현력이 풍부하고 간결해야 합니다. 하지만 AI가 생성한 130k LoC입니다. 제 생각에는 아무도 이 코드가 어떻게 작동하는지 모르고 아무도 이 코드가 실제로 작동하는지 알 수 없습니다."

Borrow Checker와의 사투

AI 생성 Rust 코드의 흔한 고충은 LLM이 borrow checker와 "전투"를 벌이는 경성향이 있다는 점입니다. 소유권 모델을 재고하기보다는, AI는 컴파일러를 만족시키기 위해 .clone()을 남발하거나 모든 것을 Arc<Mutex<...>>로 감싸는 방식을 기본값으로 선택하곤 합니다.

"LLM은 목표를 향한 직행 경로를를 선택합니다. 문제: 코드가 컴파일되지 않습니다. 해결책: 더 많은 clone()"

이는 AI가 컴파일되고 테스트를 통과할 수는 있지만, 항상 관용적인(idiomatic) Rust를 생성하지는 못할 수도 있음을 시사합니다. 즉, 안전성을 위해 liveness 이슈(예: 데드락)를 생성을 도입할 수 있다는 의미입니다.

테스트 밀도

130K 라인의 코드에 대해 1,300개의 테스트가 있다는 점에 대해, 일부는 합의 엔진과 같이 복잡한 시스템의 경우 테스트-대-코드 비율이 너무 낮다고 의문을 제항합니다. 특히 테스트 자체가 AI 생성이며 전체적으로 수동으로 검사되지 않았을 수 있다는 점을 고려할 때 말입니다.

결론

몇 달이 아닌 몇 주 만에 10만 라인이 넘는 시스템을 구축하는 것은, 유능한 설계자(architect)가 이끌어준다면 AI 에이전트가 거대한 아키텍처 작업을 수행할 수 있음을 보여줍니다. 코드 계약, 경량 스펙, 그리고 반복적인 성능 루프를를 통해, 개발자는 핵심 인프라의 중요한 부분을 성공적으로 현대화했습니다. 하지만 "코드 라인 수"와 "관용적인 품질" 사이의 긴장 관계는 차세대 AI 지원 엔지니어링의 핵심 과제로 남아 있습니다.

Sources