Anthropic 인수 후 Bun의 Rust 재작성: 월 2,200만 건의 다운로드가 높인 부담
- Ethan Carter

- 1天前
- 讀畢需時 12 分鐘
Bun은 Anthropic에 인수된 후 Rust 재작성을 완료했으며, 이제 AI가 생성한 코드베이스가 월 2,200만 건이 넘는 CLI 다운로드를 떠받치게 됐다.
이번 변화는 일상적인 프로그래밍 언어 마이그레이션보다 훨씬 큰 의미를 지닌다. Bun은 Claude의 도움을 받아 50만 줄 이상의 Zig 코드를 약 100만 줄의 Rust 코드로 변환했다고 밝혔다. 집중적인 이식 작업에는 11일이 걸렸다.
이 속도가 헤드라인을 장식했지만, 진짜 핵심은 신뢰성이다. 현재 Bun은 Claude Code, OpenCode, Prisma Compute와 예측 가능한 인프라 동작을 기대하는 개발자들을 지원한다. 이번 재작성은 컴파일러 검사, 자동화된 리뷰, 방대한 테스트 스위트가 AI 생성 시스템 코드를 신뢰할 수 있는 수준으로 만들 수 있는지를 묻는다.
동시에 불편한 역설도 생겼다. Zig는 한 명의 개발자가 1년 만에 Bun의 광범위한 기능 세트를 구축할 수 있게 했다. 하지만 바로 그 폭넓은 기능이 이후 메모리 누수, 해제 후 사용 결함, 유지보수 부담으로 이어졌고, Bun은 Rust가 이를 줄여주길 기대한다.
Anthropic 인수 후 Bun의 Rust 재작성이 바꾼 위험 구조
Bun은 유행하는 수식어를 붙이기 위해 언어를 바꾼 것이 아니다. 반복되는 메모리 오류가 운영상의 부담이 됐기 때문에 언어를 바꿨다.
Bun은 JavaScript 런타임, 패키지 관리자, 번들러, 트랜스파일러, 테스트 러너와 다수의 Node.js API 구현을 하나로 결합한다. 개발자는 일반적으로 여러 패키지가 필요한 작업을 하나의 도구로 처리할 수 있다.
하지만 그만큼 JavaScript와 네이티브 코드 사이의 경계도 많아진다. JavaScript는 더 이상 접근할 수 없는 객체를 자동으로 회수하는 가비지 컬렉션을 사용한다. Bun의 네이티브 구성 요소는 이러한 객체를 저수준 코드가 관리하는 메모리와 조율해야 한다.
이 조율 과정은 지속적인 실수의 원인이 됐다. Bun 창립자 Jarred Sumner는 최근 발생한 결함으로 해제 후 사용에 따른 충돌, 이중 해제, 범위를 벗어난 접근, 경쟁 상태, 해제되지 않은 메모리 등을 열거했다.
해제 후 사용은 소프트웨어가 메모리를 해제한 뒤 다시 접근할 때 발생한다. 그 결과는 충돌부터 예측 불가능한 동작, 보안 취약점까지 다양할 수 있다.
Bun v1.3.14에서는 압축 스트림, HTTP/2 연결, UDP 소켓, 버퍼, 암호화, TLS 세션, 파일 감시기, CSS 파서 전반에서 이러한 사례가 수정됐다. 이는 하나의 고립된 실수가 여러 형태로 나타난 것이 아니었다.
몇몇 오류는 JavaScript 콜백이 예상치 못한 시점에 네이티브 상태를 변경하면서 발생했다. 그 밖의 오류는 정리 코드가 실행되지 않거나 두 번 실행되거나, 메모리 할당 실패 후 실행되면서 생겼다.
Bun은 이미 여러 방어 수단을 활용하고 있었다. 팀은 잘못된 메모리 접근을 감지하는 런타임 도구인 AddressSanitizer를 지원하도록 Zig 컴파일러를 패치했다. 프로젝트는 모든 커밋에 대해 이러한 검사를 실행했다.
팀은 Fuzzilli도 지속적으로 사용했다. Fuzzilli는 일반 테스트가 놓칠 수 있는 엔진과 런타임 오류를 드러내기 위해 비정상적인 JavaScript 프로그램을 생성한다.
이러한 시스템은 코드가 작성된 후에야 버그를 발견했다. Sumner는 컴파일 단계에서 더 많은 소유권 관련 실수를 거부하는 프로그래밍 모델을 원했다.
Rust의 소유권 시스템은 프로그램의 어느 부분이 값을 제어하는지 추적한다. 빌림 검사기는 참조에 관한 규칙을 강제하고, Drop은 값이 범위를 벗어날 때 자동으로 정리 작업을 실행한다.
안전한 Rust는 많은 해제 후 사용 및 이중 해제 패턴을 컴파일러 오류로 바꾼다. 이는 퍼징, 지속적 통합, 프로덕션 충돌 보고서보다 더 이른 시점에 피드백을 제공한다.
따라서 Bun의 Rust 재작성은 팀이 오류가 발견될 것으로 예상하는 지점을 바꾼다. 이제 일부 실수는 바이너리가 실행되기도 전에 개발을 중단시켜야 한다.
이번 마이그레이션은 2025년 12월 3일 Anthropic의 Bun 인수 이후 진행됐다. Anthropic은 그해 11월 상당한 매출 이정표에 도달한 Claude Code에서 Bun이 중요한 인프라로 자리 잡았다고 밝혔다.
공식 Bun 인수 발표는 이 런타임을 Anthropic의 코딩 전략과 직접 연결했다. 이러한 관계는 불안정성으로 인한 비용을 높인다.
Bun에 따르면 자사 명령줄 인터페이스는 매월 2,200만 건 이상 다운로드된다. Vercel, Railway, DigitalOcean도 이 런타임을 공식 지원한다.
다운로드 횟수가 활성 개발자 수, 프로덕션 배포 수, 고유 기기 수를 의미하는 것은 아니다. 자동화된 빌드는 동일한 패키지를 반복해서 다운로드할 수 있다. 그럼에도 이 수치는 Bun이 지원해야 하는 배포 범위가 얼마나 큰지를 보여준다.
첫 번째 Rust 버전은 틈새 실험 뒤편의 새로운 구현체에 그치지 않는다. 저장소, 빌드 시스템, 배포 파이프라인 안에서 작동하는 도구들의 기반에 자리한다.
이 때문에 Anthropic 인수 후 진행된 Bun의 Rust 재작성은 두 가지 약속에 대한 시험이 된다. Rust는 흔한 메모리 관련 실수를 방지해야 하고, Claude는 그렇지 않으면 현실적으로 불가능했을 마이그레이션을 경제적으로 실행 가능하게 만들어야 한다.
이번 재작성은 두 약속이 실제 프로덕션 환경에서도 지켜지는지에 따라 평가받을 것이다.
월 2,200만 건의 다운로드로 안정성 자체가 제품이 되다
현재 Bun의 규모에서 신뢰성은 더 이상 부차적인 엔지니어링 목표가 아니다. 개발자가 설치하는 제품 자체의 일부다.
Bun은 Sumner가 esbuild의 JavaScript 및 TypeScript 트랜스파일러를 Go에서 Zig로 한 줄씩 이식하면서 시작됐다. 그는 2021년 4월에 처음으로 Zig 코드를 작성했다.
초기 버전을 구축하는 데는 약 1년이 걸렸다. Sumner는 현대적인 코딩 모델이 등장하기 전에도 그 속도를 낼 수 있었던 배경으로 Zig의 단순성과 저수준 제어 능력을 꼽았다.
이러한 출발점이 중요한 이유는 이번 재작성이 Rust와 Zig 중 단순한 승자를 가리는 일이 아니기 때문이다. Zig 덕분에 Bun은 이례적으로 폭넓은 기능 세트를 갖추고 시장에 진입할 수 있었다.
이후 Bun이 맡는 역할이 늘어나면서 수동 수명 관리 비용도 점점 커졌다. Bun의 런타임은 Safari가 사용하는 엔진인 JavaScriptCore를 여러 C 및 C++ 라이브러리와 함께 내장한다.
이러한 종속성에는 네트워킹, 암호화, 데이터베이스, 압축 구성 요소가 포함된다. 이전 Bun 코드베이스의 약 5분의 1은 이미 C++로 작성돼 있었다.
Rust가 이러한 외부 라이브러리를 자동으로 안전하게 만들 수는 없다. 외부 함수 인터페이스, 즉 FFI 경계는 Rust를 컴파일러가 메모리 규칙을 완전히 검증할 수 없는 코드와 연결한다.
다만 Rust는 이러한 상호작용을 명시적으로 표시된 unsafe 구역에 집중시킬 수 있다. 이를 통해 개발자는 컴파일러의 일반적인 보장이 더 이상 적용되지 않는 위치를 식별할 수 있다.
또한 이 언어는 일상적인 정리 작업의 일관성을 높인다. Zig에서는 일반적으로 리소스를 해제해야 하는 개별 호출 지점에 defer를 붙인다.
이 명시적 모델은 엔지니어에게 제어권을 제공하지만, 철저한 반복 작업을 요구한다. 드물게 실행되는 오류 경로에서는 정리 작업을 건너뛰거나 실수로 두 번 수행할 수 있다.
Rust의 Drop 메커니즘은 정리 작업을 객체의 수명에 연결한다. Bun은 이러한 변화가 이미 파일 경로와 빌드 데이터에 관련된 누수를 수정하는 데 도움이 됐다고 밝혔다.
한 내부 테스트에서는 60개 모듈이 포함된 프로젝트를 동일한 프로세스에서 반복적으로 번들링했다. Bun은 v1.3.14에서 빌드할 때마다 약 3MB의 메모리가 누수됐다고 보고했다.
2,000회의 빌드 후 Zig 버전은 Bun의 테스트에서 6,745MB를 소비했다. 회사에 따르면 Rust 구현은 609MB 수준에서 안정화됐다.
이 비교 결과가 다양한 워크로드에서 독립적으로 재현된 것은 아니다. 그럼에도 Bun이 제거하려는 오류 양상을 잘 보여준다.
개발 서버는 요청이나 파일 업데이트가 있을 때마다 코드를 다시 빌드할 수 있다. 프로세스가 며칠 동안 실행되면 작은 누수조차 심각한 문제가 된다.
코딩 에이전트에도 같은 우려가 적용된다. Claude Code는 파일을 검사하고 명령을 실행하며 저장소를 수정하는 과정에서 지원 프로세스를 반복적으로 실행할 수 있다.
런타임 오류는 에이전트를 중단시키거나 중간 결과를 손상시키고, 개발자가 애플리케이션이 아닌 인프라를 디버깅하게 만들 수 있다.
Claude Code는 Bun 1.4가 정식 출시되기 전에 Rust 포트로 전환했다. Bun은 6월 17일 출시된 Claude Code 버전 2.1.181이 새로운 구현을 사용했다고 밝혔다.
Bun의 프로덕션 원격 측정 데이터에 따르면 Linux의 중앙값 시작 시간은 517밀리초에서 464밀리초로 줄었다. 약 10% 개선된 수치다.
속도는 핵심 목표가 아니었다. 더 의미 있는 주장은 대부분의 사용자가 언어 변경을 알아차리지 못했다는 점이었다.
사용자가 인지하지 못하는 인프라 마이그레이션은 흔히 성공적인 마이그레이션이다. 애플리케이션의 동작은 그대로 유지하면서 그 아래의 유지보수성과 신뢰성은 개선돼야 한다.
Prisma는 또 다른 초기 프로덕션 테스트를 제공했다. 자사의 서버리스 데이터베이스 플랫폼은 Prisma Compute 공개 베타에서 Rust 재작성을 사용했다.
Prisma는 이전 구현에서 메모리 누수가 발생했으며 가상 머신이 일시 중지됐다가 재개된 후 연결 풀을 복구하지 못했다고 밝혔다. Prisma 엔지니어들은 포팅된 버전을 대상으로 이러한 시나리오를 다시 테스트했다.
Prisma의 프로덕션 평가에 따르면 새로운 구현은 이와 같은 특정 오류 양상을 처리했다. Prisma는 동시에 unsafe 코드에는 여전히 감사와 사람의 검토가 필요하다고 경고했다.
이 조합은 다운로드 횟수만으로는 드러나지 않는 부담을 더 잘 보여준다. 이번 포팅으로 측정 가능한 개선이 나타났지만, 프로덕션 환경에서 신뢰를 얻으려면 시연을 통과하는 것만으로는 부족하다.
Node.js와 Deno 역시 Bun의 발전으로 압박을 받고 있지만, 어느 쪽도 이 이야기의 핵심 경쟁 상대는 아니다. Node.js는 여전히 서버 측 JavaScript의 호환성 기준이다.
Deno는 이미 V8 JavaScript 엔진 주변에 Rust를 사용한다. 그 아키텍처는 Rust와 네이티브 종속성을 통해 JavaScript 런타임을 관리하는 데 유용한 비교 사례를 제공한다.
Bun은 성능에 관한 주장과 광범위한 툴킷을 유지하면서 Node.js 호환성도 보존해야 한다. 충돌을 줄이는 대신 동작 차이를 초래하는 재작성이라면 하나의 신뢰성 문제를 다른 문제로 바꾸는 데 불과하다.
이에 따라 팀은 즉각적인 재설계 대신 기계적인 포팅을 선택했다. 새로운 Rust 코드는 의도적으로 이전 Zig 아키텍처와 유사하게 구성됐다.
이 결정은 마이그레이션 중 동작 변화를 줄였다. 동시에 기존의 가정과 저수준 패턴을 안전 규칙이 다른 언어로 그대로 가져왔다.
그 결과 이 프로젝트의 핵심 긴장이 생겼다. Bun은 더 강력한 보장을 위해 Rust를 선택했지만, 호환성을 지키는 가장 안전한 초기 경로에서는 상당한 양의 unsafe 코드를 유지해야 했다.
Claude가 1년짜리 재작성을 11일간의 검증 루프로 바꾸다
주목할 만한 메커니즘은 단순한 코드 생성이 아니었다. 구현, 비판, 수정, 테스트를 분리한 통제된 루프였다.
Bun은 전통적인 방식으로 재작성할 경우 숙련된 엔지니어 3명이 약 1년간 투입돼야 할 것으로 추산했다. 그동안 기능 개발과 호환성 개선은 느려지거나 중단될 수밖에 없다.
기존 Zig 코드베이스는 주석을 제외하고 535,496줄이었다. 수동 포팅은 프로덕션 버전과 계속 벌어지는 장기 브랜치도 만들어낼 수 있었다.
대신 Sumner는 Claude Fable 5라는 Anthropic의 출시 전 모델을 시험했다. 그는 Zig의 패턴, 타입, 수명을 Rust로 변환하기 위한 규칙을 만드는 데 약 3시간을 들였다.
Claude는 이러한 결정을 포팅 가이드에 기록했다. 별도로 생성된 두 번째 문서에는 코드베이스 전반의 필드에 예상되는 수명이 정리됐다.
팀은 처음부터 모든 것을 변환하지 않고 파일 3개로 시작했다. 각 포팅은 한 Claude 인스턴스가 구현하고, 별도의 인스턴스 2개가 검토했으며, 또 다른 인스턴스가 수정 사항을 적용했다.
이러한 분리는 의도적인 선택이었다. 변경 사항을 만든 모델은 자신의 추론을 스스로 받아들이는 방향으로 편향될 수 있기 때문이다.
검토를 맡은 인스턴스들은 구현자의 전체 맥락 없이 diff를 전달받았다. 이들에게 주어진 역할은 잘못된 동작과 회귀를 찾아내는 것이었다.
Sumner는 이를 적대적 검토라고 불렀다. 독립적인 코드 리뷰와 유사하지만, 모든 참여자가 동일한 모델 계열의 인스턴스였다는 차이가 있다.
전체 작업에는 약 50개의 동적 Claude Code 워크플로가 사용됐다. 정점에는 4개 워크플로 그룹이 동시에 실행됐으며, 각 그룹은 16개의 Claude 인스턴스를 조율했다.
이는 약 64개의 에이전트가 동시에 작업했다는 뜻이다. 포팅 작업은 분당 약 1,300줄이 생성되는 최고 속도에 도달한 것으로 전해졌다.
처음부터 과정이 순조로웠던 것은 아니다. 동일한 저장소에서 작업하던 에이전트들이 stash 작업과 hard reset을 포함해 서로 충돌하는 Git 명령을 사용했다.
Sumner는 광범위한 Git 작업을 금지하도록 지침을 수정했다. 이후 시스템은 4개의 별도 worktree를 사용했으며, 에이전트들은 특정 파일을 커밋하고 브랜치를 통해 결과를 공유했다.
이 실패는 모델의 역량만으로는 재작성이 완성되지 않았음을 보여준다는 점에서 중요하다. 워크플로에는 공유 상태와 파괴적 작업을 둘러싼 명시적인 제약이 필요했다.
유사한 마이그레이션을 검토하는 팀에도 그만큼 명확한 운영 규칙이 필요하다. 올바른 코드를 작성하는 에이전트라도 저장소, 자격 증명, 빌드 시스템 또는 배포 도구를 잘못 다루면 작업을 훼손할 수 있다.
마이그레이션 과정에서는 병합을 제외하고 6,502개의 커밋이 생성됐으며, Bun은 11일 동안 총 6,778개의 커밋이 이뤄졌다고 밝혔다. 최종 반영된 diff에는 100만 줄이 조금 넘는 코드가 추가됐다.
이 수치들은 활동량을 나타낼 뿐 품질을 말해주지는 않는다. 작은 커밋은 추적 가능성을 높일 수 있지만, 수천 개의 자동화된 커밋은 기존의 인간 중심 리뷰 방식으로 감당하기 어렵다.
Bun은 주로 컴파일러, 자동화된 리뷰어, 기존 테스트 스위트에 의존했다. 이 스위트에는 지원 플랫폼 전반에 걸쳐 약 100만 개의 assertion이 포함돼 있었다.
병합 전 팀은 지속적 통합에서 테스트 완료율 100퍼센트를 기록했다고 밝혔다. 삭제되거나 건너뛴 테스트는 없었다고도 설명했다.
Debian에서 Bun은 60,624개 테스트에 걸쳐 1,386,826회의 expect() 호출을 기록했다. macOS와 Windows에서도 각각 100만 개가 넘는 assertion이 실행됐다.
테스트 스위트가 TypeScript로 작성됐다는 점은 Bun에 중요한 이점이었다. 테스트는 내부 런타임이 Zig를 사용하는지 Rust를 사용하는지에 의존하지 않고 관찰 가능한 동작을 평가했다.
이 아키텍처 덕분에 기계적인 포팅을 측정할 수 있었다. 번역된 각 컴포넌트는 동일한 외부 테스트가 이미 기대하던 결과를 유지해야 했다.
Claude는 컴파일러 오류도 작업 대기열로 처리했다. Bun은 Rust 코드를 약 100개의 crate로 분할했는데, crate는 Rust 프로젝트에서 개별적으로 컴파일되는 패키지다.
한 단계에서는 cargo check가 약 16,000개의 오류를 출력했다. 워크플로는 이러한 실패를 crate별로 묶어 에이전트에게 할당하고, 수정 사항을 검토한 뒤 같은 과정을 반복했다.
컴파일 루프는 막막해 보이던 마이그레이션을 범위가 정해진 작업들로 전환했다. 각 오류는 에이전트가 조치할 수 있는 국소적 피드백을 제공했다.
이 접근법은 Rust 컴파일러가 많은 소유권 및 타입 오류를 정밀하게 설명하기 때문에 특히 효과적이었다. 컴파일러는 관문인 동시에 구조화된 지침의 원천이 됐다.
병합 전까지 이 과정에는 캐시되지 않은 입력 토큰 59억 개와 출력 토큰 6억 9,000만 개가 소비됐다. 캐시된 입력 토큰도 720억 개 읽었다.
Bun은 API 가격을 기준으로 총비용을 약 16만 5,000달러로 추산했다. 이 금액에는 기존 코드베이스, 테스트, 인간의 전문성, 이후의 유지보수를 비롯한 모든 조직적 비용이 포함되지는 않는다.
따라서 엔지니어 3명이 1년 동안 작업하는 경우와의 비교는 대략적인 방향성을 보여줄 뿐 완전한 비교는 아니다. Claude가 Bun의 아키텍처, 호환성 작업, 테스트 코퍼스를 무에서 만들어낸 것은 아니다.
Claude는 수년에 걸쳐 축적된 엔지니어링 맥락을 활용했다. 마이그레이션 속도는 에이전트가 읽고 검증할 수 있는 형식으로 그 맥락이 제공됐기에 가능했다.
이 차이는 다른 팀에도 중요하다. 성숙한 테스트 스위트와 명확하게 정의된 동작이 있다면 자동화된 마이그레이션이 현실적인 선택지가 될 수 있다.
테스트가 부실한 시스템에는 이에 상응하는 판정 기준이 없다. 에이전트가 컴파일되는 코드를 만들어내더라도 사용자가 의존하는 동작을 조용히 바꿔버릴 수 있다.
엔지니어링 팀에는 에이전트의 의사결정을 설명하는 지속 가능한 기록도 필요하다. 검색 가능한 지식 베이스는 개별 컨텍스트 창의 한계를 넘어 마이그레이션 규칙, 리뷰 결과, 소유권에 관한 가정을 보존할 수 있다.
Bun 프로젝트에서는 포팅 문서, 수명 맵, 커밋 기록, 테스트가 이 역할을 했다. 이러한 산출물은 부수적인 행정 자료가 아니었다.
고속으로 생성된 코드를 검토 가능한 상태로 만든 것은 바로 이 체계였다.
Bun에 여전히 Unsafe 코드가 남아 있는 한 Rust도 안전을 보장할 수 없다
이번 재작성은 여러 유형의 위험을 줄이지만, 그렇다고 Bun이 자동으로 메모리 안전성을 확보했다고 간주할 수는 없다.
Bun의 기계적 번역은 저수준 포인터 연산과 C 및 C++ 라이브러리와의 광범위한 상호작용을 그대로 유지했다. 이러한 영역에서는 Rust의 unsafe 키워드가 필요한 경우가 많다.
unsafe 블록은 borrow checker가 검증할 수 없는 연산을 허용한다. 프로그래머가 필요한 규칙을 직접 준수해야 한다.
그렇다고 모든 unsafe 블록에 결함이 있다는 뜻은 아니다. 주요 Rust 시스템들은 효율적인 추상화를 구현하고 운영체제나 네이티브 라이브러리와 연결하기 위해 unsafe 코드를 사용한다.
다만 Rust의 가장 중요한 보장은 그러한 경계를 어떻게 설계하고 문서화하며 감사하는지에 달려 있다는 의미다.
Sumner는 초기에 Bun Rust 코드의 약 4퍼센트가 unsafe 블록 안에 있었다고 밝혔다. 약 780,000줄의 Rust 코드 가운데 약 27,000줄이 unsafe 코드였다고 설명했다.
또한 해당 블록의 78퍼센트는 한 줄로 구성됐다고 말했다. 상당수는 C++ 포인터 하나를 처리하거나 네이티브 라이브러리를 한 번 호출하는 코드였다.
이러한 설명은 참고할 만하지만, 블록 길이만으로 정확성을 입증할 수는 없다. unsafe 포인터 변환 한 번이 수명 오류를 일으켜 다른 곳의 safe 코드에까지 영향을 미칠 수 있다.
5월 14일 공개된 메모리 안전성 문제는 이러한 우려를 입증했다. 보고서는 safe 함수가 slice 수명을 지워 dangling reference를 허용하는 사례를 보여줬다.
Rust 프로그램의 정의되지 않은 동작을 감지하는 데 사용되는 인터프리터인 Miri가 이 사례를 포착했다. 정의되지 않은 동작이란 언어가 결과에 대해 신뢰할 만한 제약을 두지 않는 상태를 뜻한다.
Bun의 자동화된 기여자는 문제를 재현하고 이와 유사한 또 다른 수명 허점을 찾아냈다. 제안된 수정안은 영향을 받는 함수들을 unsafe로 표시하고 수명 요구사항을 문서화했다.
이 대응은 프로젝트가 구체적인 보고를 신속히 처리할 수 있음을 보여줬다. 동시에 컴파일과 기존 테스트 스위트만으로는 모든 잘못된 추상화를 막지 못했음도 드러냈다.
이 간극은 재작성에 대한 가장 강력한 회의론을 뒷받침한다. 자동화된 테스트가 Zig의 메모리 오류를 놓쳤다면, 동일한 테스트로 대규모 Rust 포팅의 건전성을 입증할 수는 없다.
Rust는 컴파일러를 통한 강제 검증을 추가하지만, unsafe 영역에서는 책임이 다시 엔지니어에게 돌아간다. 기계적 번역은 해당 영역에서 기존의 포인터 처리 방식을 그대로 보존할 수 있다.
Zig 창시자 Andrew Kelley는 가장 날카로운 공개 비판을 내놓았다. 그의 재작성 관련 견해는 Bun의 문제가 Zig의 실패가 아니라 엔지니어링 관행과 누적된 기술 부채에서 비롯됐다고 주장했다.
Kelley는 모델이 생성한 방대한 코드가 충분한 인간의 검토를 거쳤는지에도 의문을 제기했다. 그의 비판은 일부 대목에서 인신공격적으로 흘러 기술적 쟁점에 대한 집중을 흐렸다.
그러나 그 질문 자체는 여전히 유효하다. 팀이 AI 생성 재작성을 신뢰하기 전에 인프라에는 어느 수준의 독립적 검토가 필요할까?
Bun은 모든 코드 줄이 서로 다른 두 Claude 인스턴스의 검토를 받았다고 밝혔다. 하지만 모델 리뷰가 독립적인 인간의 판단과 같지는 않다.
동일한 모델의 인스턴스들은 맹점, 학습 패턴, 잘못된 가정을 공유할 수 있다. 컨텍스트 창을 분리하면 앵커링은 줄일 수 있지만, 진정으로 독립적인 전문성이 생기지는 않는다.
자동화된 리뷰어들은 병합 전에 개연성 있는 버그 몇 가지를 포착했다. 그중 하나는 리소스를 두 번 해제할 수 있는 비동기 close 작업과 관련된 문제였다.
또 다른 버그는 음수 timestamp를 잘못 처리했다. 세 번째는 특정 CSS 색상 표현식을 파싱할 때 panic을 일으킬 수 있는 eager Rust 메서드를 사용했다.
이 사례들은 적대적 검토가 실질적인 가치를 제공했음을 보여준다. 하지만 모든 검토 에이전트가 함께 놓친 결함이 얼마나 되는지는 알려주지 않는다.
논쟁을 AI 생성 코드를 받아들일지 거부할지의 양자택일로 축소해서는 안 된다. 더 유용한 질문은 보증 수준에 관한 것이다.
팀들은 이미 컴파일러, 정적 분석기, fuzzer, 형식 모델, 자동화된 테스트 시스템을 신뢰하고 있다. 코딩 에이전트도 최종 권위자가 되지 않는 한 이 도구 집합에 합류할 수 있다.
Prisma의 입장은 실용적인 중간 지점을 제시한다. Prisma는 공개 베타에 포팅 버전을 배포했으며, 알려진 실패 시나리오에서 개선이 있었다고 보고했다.
동시에 Prisma는 unsafe 코드에 대한 감사와 번역된 코드에 대한 검토가 필요하다고 밝혔다. 또한 비관용적인 부분을 인간이 이해할 수 있는 단위로 리팩터링할 것을 권고했다.
Bun도 이와 유사한 방침을 밝혔다. 초기 목표는 동작을 보존하는 것이었으며, 이후 unsafe 사용을 줄이고 더욱 관용적인 Rust를 채택하는 작업을 점진적으로 진행한다는 계획이다.
이러한 순서는 충분히 타당하지만, 안전성 측면의 이점 일부를 뒤로 미룬다. unsafe 영역이 축소될 때까지 마이그레이션은 계속 진행 중인 엔지니어링 프로그램으로 남는다.
논점은 메모리 안전성을 넘어선다. 런타임은 잘못된 모듈 해석, 호환되지 않는 API, 네트워킹 동작, 성능 저하 또는 운영체제 간 미묘한 차이로도 실패할 수 있다.
Rust는 논리 오류를 막지 못한다. 100만 개의 assertion을 갖춘 테스트 스위트도 유통되는 모든 JavaScript 패키지에서 올바른 동작을 보장하지는 못한다.
따라서 Bun에는 외부 워크로드, 독립적인 감사, fuzzing, 장기간의 프로덕션 배포가 필요하다. 각각은 내부 검증만으로는 얻을 수 없는 증거를 제공한다.
Anthropic 인수 이후 이뤄진 Bun Rust 재작성은 현재 적극적인 검증이 진행 중인 유망한 마이그레이션으로 봐야 한다. 이를 완전한 안전성 성공이나 자동화의 실패로 단정하는 것은 현재 확보된 증거를 넘어선 판단이다.
Bun 재작성의 성공 여부를 결정할 세 가지 신호
다음 단계는 11일간의 포팅만큼 극적이지는 않지만, 이번 재작성이 모범 사례가 될지 경고 사례가 될지를 결정할 것이다.
첫 번째 신호는 일반적인 프로덕션 배포 환경에서 나타나는 Bun 1.4의 동작이다. Bun v1.3.14는 마지막 Zig 릴리스였으며, v1.4부터 Rust 구현이 도입됐다.
팀들은 폭넓은 도입 이후의 crash 보고, 메모리 소비, 호환성 회귀, rollback을 주시해야 한다. 성공적인 릴리스라면 새로운 유형의 동작 버그를 만들지 않으면서 메모리 오류를 줄여야 한다.
초기 Claude Code 및 Prisma 배포 결과는 Bun의 주장을 뒷받침한다. 하지만 패키지 조합, 운영체제, 네이티브 모듈, 워크로드 패턴의 전체 다양성을 포괄하지는 않는다.
광범위한 사용은 Bun의 내부 테스트 스위트가 한 번도 도달하지 못한 코드 경로를 드러낼 것이다. 여러 릴리스 주기에 걸쳐 안정적인 결과가 이어져야 출시 시점의 벤치마크보다 강한 증거가 된다.
두 번째 신호는 Bun의 unsafe Rust 영역 규모와 설계다. FFI 비중이 높은 런타임은 unsafe 코드를 완전히 제거할 수 없으므로 단순한 개수에는 맥락이 필요하다.
더 의미 있는 질문은 unsafe 연산이 작고 문서화된 인터페이스 뒤로 이동하는지다. 각 인터페이스는 호출자가 준수해야 하는 수명, aliasing, 소유권, thread safety 관련 가정을 명시해야 한다.
독립적인 감사는 이 작업의 신뢰도를 높일 수 있다. 공개된 Miri 조사 결과, sanitizer 결과, fuzzing 결과에도 regression test를 포함한 명확한 수정이 뒤따라야 한다.
Bun이 성능과 호환성을 유지하면서 unsafe 사용량을 줄인다면 재작성에 관한 안전성 주장은 더욱 강해질 것이다. safe 인터페이스 안에서 수명 오류가 반복된다면 그 주장은 약해질 수밖에 없다.
세 번째 신호는 또 다른 성숙한 프로젝트가 Bun의 마이그레이션 방식을 재현하는지 여부다. Bun은 광범위한 테스트, 단일 핵심 설계자, 출시 전 모델에 접근할 수 있는 소유자라는 이례적으로 유리한 출발 조건을 갖추고 있었다.
두 번째로 성공한 마이그레이션으로 인정받으려면 빠른 코드 생성 이상의 성과를 보여줘야 한다. 사람의 검토, 결함 발견, 운영 통제, 출시 후 유지보수 과정을 문서로 입증해야 한다.
이러한 성과가 반복된다면, AI 지원 언어 마이그레이션은 수년간 누적된 재작성 비용에 발이 묶인 프로젝트에서 일반적인 선택지로 자리 잡을 수 있다.
반면 Bun이 일회성 사례에 그친다면 여기서 얻을 수 있는 교훈의 범위는 더 좁아질 것이다. 이 성과는 여전히 의미가 있지만, 일반적인 소프트웨어 개발보다는 Bun의 테스트 인프라가 얼마나 뛰어난지를 보여주는 사례에 가까워진다.
더 큰 경쟁 구도는 Rust와 Zig의 대결이 아니다. 머신이 만들어내는 속도와 기반 소프트웨어를 신뢰하는 데 필요한 증거 사이의 대결이다.
Bun은 이 경쟁을 장난감 수준의 프로젝트에서 월간 다운로드 2,200만 회를 넘는 런타임으로 끌어올렸다. Anthropic은 공개 논쟁이 결론 나기도 전에 그 결과물을 Claude Code에 적용했다.
이 선택으로 Bun은 귀중한 프로덕션 피드백을 얻을 수 있다. 동시에 Anthropic은 자사의 코딩 에이전트가 생성한 것을 지속적으로 유지보수할 수 있다는 사실을 입증해야 할 책임도 지게 됐다.
개발자는 위험도가 높은 마이그레이션을 결정하기 전에 릴리스 노트, 해결되지 않은 안전성 보고서, 독립적인 배포 결과를 면밀히 살펴봐야 한다. 또한 현실적인 부하 환경에서 자체 종속성을 테스트해야 한다.
Anthropic 인수 이후 진행된 Bun의 Rust 재작성은 AI 지원 포팅이 이전에는 불가능하다고 여겨졌던 규모의 장벽을 넘어설 수 있음을 이미 보여줬다.
남은 쟁점은 검증 프로세스가 생성 프로세스의 속도를 따라갈 수 있느냐다. Bun 1.4의 실제 운영 성능과 unsafe 코드 감사 결과, 그리고 같은 방식을 시도할 다음 대규모 프로젝트를 지켜봐야 한다.