Bun의 Rust 재작성, Zig의 역할, AI 생성 코드의 검토 부재, 그리고 장기 유지보수 위험에 대한 생각.
Bun을 Rust로 재작성하는 이야기를 하기 전에, 아무도 말하지 않는 어떤 점은 먼저 짚고 넘어가야 한다.
오늘의 Bun이 여기까지 올 수 있었던 것은 Zig 덕분이다.
Jarred가 당시 Zig를 선택한 이유는 그것이 "멋져서"가 아니라, GC도 없고 무거운 런타임도 없이 소규모 팀이 고성능 JS 런타임을 빠르게 프로토타이핑할 수 있게 해주었기 때문이다. Zig의 낮은 마찰, 직접적인 메모리 조작, 단순한 C 상호운용성은 초기의 매우 작은 팀으로도 Bun이 성능 면에서 체급 이상을 발휘할 수 있었던 핵심 이유였다. 오늘날 보이는 Bun의 아키텍처, 자료구조, 저수준 설계는 Zig에 의해 형성되었다.
Jarred 본인도 말했다. 아키텍처는 바뀌지 않고, 자료구조도 바뀌지 않는다.
평이하게 말하면: Rust 재작성판이 물려받은 골격은 Zig로 세워졌다. Zig로 기초를 만들고, Zig로 제품을 출시하고, Zig로 투자를 유치한 뒤, 회사가 인수되고 충분히 성장한 다음 더 "주류"인 기술 스택으로 전환하는 것은 전혀 잘못이 아니다. 이것은 정상적인 사업적 결정이다. 실리콘밸리 스타트업에서 기술 부채는 원래 그렇게 작동한다.
Zig 커뮤니티가 Bun의 감사를 필요로 하지는 않지만, 이번 재작성이 Zig 자체가 부족해서 일어났던 것처럼 가장하지는 말아 달라.
이제 그 재작성 자체를 이야기해 보자.
커밋 6,755개, 브랜치 이름은 claude/phase-a-port, PR은 5월 8일에 열렸고 5월 14일에 머지되었다.
6일. 프로덕션급 JS 런타임 전체 재작성이 6일 만에 머지되었다.
이 숫자를 잠깐 머릿속에 두고 생각해 보라.
소프트웨어 공학에는 근본적인 원칙이 하나 있다. 이해하지 못하는 코드는 프로덕션에서 돌아가면 안 된다. 반드시 버그가 있어서가 아니라, 실제로 문제가 생겼을 때 어디서부터 봐야 할지조차 알 수 없기 때문이다. 이것은 보수주의가 아니라 유지보수 가능성의 최저선이다.
커밋 6,755개, 사람이 직접 쓴 줄은 단 한 줄도 없다. PR의 리뷰어 목록을 보면 coderabbitai[bot]가 리뷰했고, claude[bot]도 리뷰했고, 유일한 인간 리뷰어인 alii의 상태는 "Awaiting requested review"였다. 즉, 아직 보지도 않았다.
Claude가 작성한 코드를 Claude가 리뷰했다. 이런 폐쇄 루프가 논리적으로 불가능한 것은 아니지만, 이것이 의미하는 바는 분명하다. 이 코드베이스 전체를 실제로 읽은 사람은 아무도 없었다.
여기서 누군가는 반박할 것이다. 모든 플랫폼에서 테스트 스위트가 통과했는데, 그것이 검증 아닌가?
아니다.
테스트 스위트는 알려진 경로에서의 알려진 동작의 정확성을 검증한다. 다음을 검증하지는 않는다.
Jarred 본인도 인정했다. JS 경계를 넘어 재진입할 때의 메모리 문제는 Rust 컴파일러가 처리할 수 없고, 여전히 인간에게 의존한다고.
그리고 그 인간에게 의존하는 부분은? 그 부분을 검토한 인간은 아무도 없었다.
더 근본적인 문제는 AI가 코드를 국소적 의미 동등성을 기준으로 번역한다는 점이다. 즉, 각 함수가 고립된 상태에서 원본과 동일하게 동작하도록 만들 수는 있어도, 함수들 사이의 전역 불변식은 이해하지 못한다. 테스트에 적혀 있지 않고 원저자의 머릿속에만 존재하는 설계 제약들 말이다. 이런 제약은 오늘의 테스트에서는 드러나지 않을 수 있지만, 6개월 뒤 특정한 프로덕션 부하 아래에서 전혀 설명할 수 없는 크래시로 나타날 수 있다.
이것은 Claude를 깎아내리는 말이 아니다. 철저한 리뷰 없이 번역 도구라면 무엇이든, 인간 프로그래머를 포함해서, 마주하게 되는 문제다. 6,755개 커밋 규모에서는 이 위험이 6,755배 증폭된다.
여기에는 기술 논의에서 보통 무시되는 정치경제적 차원도 있다.
초기의 Bun은 Jarred가 자기 자신에게 거는 베팅이었다. 그 시기에 Zig를 사용하고, 빠르게 반복하고, 기술 부채를 감수하는 것은 스스로 위험을 떠안는 스타트업의 논리로서 타당했다.
하지만 이제 Bun은 대기업에 인수되었고, 사용자층은 실제 프로덕션 시스템으로 이루어져 있다. 이번 재작성이 초래하는 위험을 떠안는 주체는 더 이상 Jarred가 아니라, 프로덕션에서 Bun을 돌리는 모든 엔지니어와 그 뒤에 있는 사용자들이다.
Jarred는 이 버전이 아직 canary 상태이며, 공식 릴리스 전까지 최적화와 정리 작업이 더 필요하다고 말했다.
Canary는 방어선 중 하나이지만, 인간의 리뷰는 아니다. 최적화와 정리는 코드 품질의 문제이지, 이해의 문제가 아니다. 팀 내 누구도 끝까지 읽어보지 않은 코드베이스는, 테스트가 아무리 포괄적이어도, canary를 아무리 오래 돌려도, 유지보수자에게는 내부 상태가 블랙박스다.
이 점은 미래의 어떤 심각한 버그를 디버깅하는 현장에서 아주 현실적인 고통으로 돌아올 것이다.
이제 Jarred가 이주 이유로 제시한 내용으로 돌아가 보자. Zig 코드베이스에는 use-after-free 버그, double-free, 그리고 오류 경로에서의 메모리 누수가 너무 많았다는 것이다.
이 말 자체는 사실이다. 하지만 이 진단에서 "Zig는 안 된다"는 결론을 끌어내는 것은 틀렸다.
올바른 진단은 이것이다. 빠른 반복을 우선시하는 상용 프로젝트에서는 수동 메모리 관리의 인지적 비용이 팀의 예산을 넘어섰다. 이것은 Zig의 버그가 아니라, Zig의 설계 목표와 Bun의 사업 모델 사이의 구조적 불일치다.
Zig의 대상 사용자는 자신이 무엇을 하는지 알고, 궁극적인 제어를 위해 그 대가를 기꺼이 치를 시스템 프로그래머들이다. TigerBeetle이 Zig로 사실상 메모리 버그가 없는 데이터베이스를 쓸 수 있었던 이유는 그들의 팀 문화와 프로젝트 성격이 Zig의 철학과 맞아떨어지기 때문이다.
Bun 팀의 문화는 빠른 반복, 빠른 출시, 빠른 버그 수정이다. 이것은 Zig가 요구하는 엄격한 메모리 규율과 근본적인 긴장을 이룬다. 이것은 Zig의 실패가 아니라 Bun과 Zig 사이의 부조화다.
"우리 팀은 이 도구로 자주 실수한다"를 "이 도구는 불충분하다"로 해석하는 것은 귀인 오류다. 망치가 맞지 않을 수는 있지만, 그렇다고 망치의 잘못은 아니다.
솔직히 말하면: 단기적으로는 아마 괜찮겠지만, 장기적으로는 구조적 위험이 있다.
단기적으로는 테스트가 주요 경로를 덮고 있고, canary 단계에서 명백한 문제들이 드러날 것이며, Rust 컴파일러의 보장은 메모리 버그의 한 부류를 통째로 제거해 준다. 겉으로 보기에는 모든 것이 정상처럼 보인다.
장기적으로는 이 코드베이스에 사람이 끝까지 읽지 않은 6,755개의 커밋이 존재한다. 6개월 뒤 기묘한 동시성 버그가 나타나거나, 특정 부하 아래에서 어떤 경계 조건이 이상 동작을 촉발할 때, 그 문제를 디버깅하는 엔지니어는 누구도 진정으로 이해한 적 없는 시스템과 마주하게 될 것이다.
아무도 이해하지 못한 시스템은 버그가 없다는 뜻이 아니다. 버그가 나타났을 때 왜 그런지 아는 사람이 없다는 뜻이다. 이 둘의 차이는 새벽 3시의 프로덕션 장애 상황에서 극명하게 드러난다.
이것이 이번 재작성이 걸고 있는 진짜 기술적 베팅이다. Zig 대 Rust가 아니라, AI가 생성했고 검토되지 않은 코드가 프로덕션 환경에서 장기적으로 유지보수될 수 있는가라는 질문이다.
이 질문은 "모든 테스트 통과"보다 훨씬 복잡하고, "Rust 메모리 안전성"보다 훨씬 더 깊다.
답은, 지켜봐야 알 것이다.
Zig가 기초를 세웠고, Claude가 건물을 올렸으며, 인간 리뷰어들은 아직 오는 중이다.
이 건물이 첫 번째 누수를 일으켰을 때에도 계속 사람이 살 수 있는지는, 누군가가 설계도를 읽어낼 수 있는지에 달려 있다.