Bun 1.4: AI를 활용한 Rust 런타임 재작성
Bun 1.4: AI를 활용한 Rust 런타임 재작성
Bun은 v1.4.0 릴리스를 위해 핵심 런타임을 Rust로 재작성했습니다. 이를 통해 메모리 안전 취약점을 체계적으로 제거하고 안정성을 향상시켰습니다. Claude Fable 5 사전 릴리스 버전과 자동화된 "adversarial review" 워크플로우를 활용해 팀은 11일 만에 500,000줄 이상의 Zig 코드를 Rust로 포팅했으며, 바이너리 크기를 20% 줄이고 성능을 2~5% 향상시켰습니다.
왜 Bun이 Zig에서 Rust로 이동했는가
Bun은 처음에 저수준 제어와 높은 성능을 활용하기 위해 Zig로 구축되었습니다. 그러나 트랜스파일러, 패키지 매니저, 테스트 러너, Node.js API 구현 등을 포함하는 방대한 프로젝트 범위는 상당한 안정성 문제를 야기했습니다.
체계적인 메모리 안전 문제
재작성의 주요 동기는 스타일 가이드나 수동 리뷰만으로는 해결하기 어려운 반복적인 메모리 버그 클래스였습니다. Bun v1.3.14에서 팀은 다음과 같은 다수의 치명적인 이슈를 발견했습니다:
- Use-after-free 충돌:
node:zlib와node:http2에서 비동기 작업이나 재진입 JS 콜백에 의해 발생. - Double-free 충돌: CSS 파서에서 발생.
- 메모리 누수:
crypto.scrypt,tlsSocket.setSession(),fs.watch()에서 레퍼런스 카운트 언더플로우 또는 정리 호출 누락으로 발생.
팀은 Address Sanitizer(ASAN)와 24/7 Fuzzilli 퍼징을 사용했지만, Zig의 자동 메모리 관리 부재로 인해 모든 할당을 세심하게 수동 검토해야 했습니다. Rust는 빌림 검사기와 Drop 트레이트 덕분에 이러한 메모리 안전 오류를 컴파일러 오류로 전환시켜, 수동 코드 리뷰보다 빠르고 신뢰할 수 있는 피드백 루프를 제공했습니다.
AI 기반 재작성 프로세스
전통적인 점진적 재작성은 종종 임시 "접착" 코드를 도입하지만, Bun 팀은 전체 코드베이스를 기계적으로 포팅했습니다. 이는 Claude Code와 일련의 동적 워크플로우를 활용해 달성되었습니다.
"Adversarial Review" 워크플로우
LLM이 생성한 코드의 품질을 보장하기 위해 팀은 분할 컨텍스트 리뷰 시스템을 구현했습니다:
- Implementer: 원본 Zig 소스와 포팅 가이드를 기반으로 Rust 코드를 작성하는 Claude 인스턴스.
- Adversarial Reviewers: diff만을 받는 두 개의 별도 Claude 인스턴스. 그들의 유일한 목표는 버그를 찾고 코드가 잘못되었음을 증명하는 것.
- Fixer: 리뷰어들의 피드백을 적용하는 최종 인스턴스.
이 프로세스는 js_bun_spawn_bindings.rs에서 비동기 uv_close에 의해 발생한 use-after-free/double-free 버그와 같이 표준 컴파일러 검사를 통과했을 버그들을 잡아냈습니다.
실행 및 규모
- 타임라인: 11일 (5월 3일 ~ 5월 14일).
- 볼륨: 6,502 커밋, 분당 최대 1,300줄 코드 출력.
- 인프라: 4개의 워크트리에서 64개의 동시 Claude 인스턴스 실행.
- 비용: API 토큰 비용 약 $165,000.
Bun v1.4.0의 기술적 개선 사항
메모리 사용량 및 안정성
Rust의 Drop 트레이트 도입으로 여러 계측 가능한 메모리 누수가 사라졌습니다. 예를 들어 Bun.build()에서 v1.3.14는 빌드 수가 증가함에 따라 메모리 사용량이 선형적으로 증가해 2,000번 빌드 후 6.7 GB에 도달했지만, v1.4.0에서는 약 609 MB 수준으로 안정됩니다.
바이너리 크기와 성능
- 바이너리 크기: Linux와 Windows에서 약 20% 감소 (예: Windows 바이너리가 94 MB에서 76 MB로 축소). 이는
comptime사용 감소와 Identical Code Folding 같은 링커 최적화 덕분입니다. - 처리량: HTTP 처리량이 다양한 프레임워크(Bun.serve, Elysia, Fastify)에서 2.8%~4.8% 증가.
- CLI 속도:
next build와tsc -b같은 앱 워크로드에서 2.2%~4.7% 성능 향상. - 스택 공간: 재귀 하강 파서(JSON, TOML 등)가 LLVM의
llvm.lifetime.start와llvm.lifetime.end내재 함수를 사용해 스택 사용량 감소.
포팅 도전 과제와 회귀
자동화된 프로세스에도 불구하고 재작성 과정에서 19개의 알려진 회귀가 발생했으며, 대부분은 Zig와 Rust 사이의 의미 차이에서 비롯되었습니다:
- 매크로 소거: Rust의
debug_assert!가 릴리즈 빌드에서 부수 효과 호출(insert_stale)을 소거해 특정 React 프로젝트의 HMR이 깨졌습니다. 반면 Zig의assert는 항상 실행되는 함수입니다. - 슬라이스 처리: Rust의
bytemuck::cast_slice는 길이가 홀수인 슬라이스에서 패닉을 일으키지만, 원래 Zig 코드는 남은 바이트를 무시했습니다. 이로 인해 특정 UTF-16 경우에Blob.text()가 패닉 발생. - 범위 검사: Rust 릴리즈 빌드는 범위 검사를 유지해 Zig의
ReleaseFast모드에서 숨겨졌던 모듈 해석기의 오프바이원 오류가 드러났습니다.
커뮤니티와 산업 관점
Hacker News 토론에서 소프트웨어 엔지니어링 패러다임의 변화를 강조했습니다:
"포괄적인 테스트 하네스를 설계하고 구현하는 것이 진짜 작업이다. 그것을 갖추면 LLM에게 맡겨라."
비평가들은 높은 토큰 비용($165k)이 인간 팀 대비 일부 노동 절감 효과를 상쇄할 수 있다고 지적했으며, 다른 이들은 재작성 성공이 Bun의 기존 언어 독립적인 TypeScript 테스트 스위트에 크게 의존했으며, 이는 AI가 효과적으로 반복할 수 있는 "검증 가능한 보상"을 제공했다고 언급했습니다.
요약: Bun은 버전 1.4.0에서 Zig에서 Rust로 전환하여 메모리 안전 버그를 체계적으로 제거했으며, 그 결과 바이너리 크기가 20% 작아지고 성능이 향상되었습니다.
제목: Bun 1.4: AI를 활용한 Rust 런타임 재작성