1P by GN⁺ 3시간전 | ★ favorite | 댓글 1개
  • Bun의 Rust 재작성은 Zig로 만든 기존 아키텍처와 자료구조를 유지한 채 더 주류 기술 스택으로 옮기는 결정에 가까움
  • 재작성 PR은 6,755개 커밋 규모였고 5월 8일 오픈 후 5월 14일 병합돼, 프로덕션급 런타임 변경의 리뷰 깊이에 의문이 남음
  • 테스트 통과는 알려진 경로만 검증하며, 에러 경로·동시성·극단적 메모리 조건 같은 전역 불변식까지 보장하기 어려움
  • 핵심은 Zig의 실패가 아니라 빠른 출시를 중시하는 Bun 팀 문화와 수동 메모리 관리 비용 사이의 구조적 불일치에 있음
  • 실제 베팅은 Zig 대 Rust가 아니라, AI가 생성하고 충분히 리뷰되지 않은 코드를 장기 유지보수할 수 있는지에 있음

Zig가 만든 Bun의 기반

  • Bun의 Rust 재작성 PR을 보기 전에, Bun이 현재 위치에 오른 데에는 Zig의 역할이 컸음
  • Jarred가 Zig를 선택한 이유는 “멋있어서”가 아니라, 가비지 컬렉션 없는 고성능 JS 런타임을 작은 팀이 빠르게 프로토타입으로 만들 수 있었기 때문임
  • Zig의 낮은 마찰, 직접적인 메모리 조작, 단순한 C 상호 운용성이 Bun 초기 성능과 작은 팀 규모를 가능하게 했음
  • Jarred가 “아키텍처는 바뀌지 않고, 자료구조도 바뀌지 않는다”고 말한 만큼, Rust 재작성은 Zig로 만들어진 골격을 이어받는 구조에 가까움
  • Zig로 기반을 만들고, 제품을 출시하고, 투자 유치까지 한 뒤 회사가 인수되고 커진 다음 더 주류 기술 스택으로 옮기는 일은 정상적인 비즈니스 결정으로 볼 수 있음
  • 다만 이를 Zig 자체의 부적합성으로 포장하기는 어려움

6일 만에 병합된 대규모 재작성의 위험

  • 재작성 PR6,755개 커밋, 브랜치명 claude/phase-a-port, 5월 8일 오픈 후 5월 14일 병합이라는 기록을 남김
  • 프로덕션급 JS 런타임 전체 재작성이 6일 만에 병합됐다는 점이 핵심 문제임
  • 소프트웨어 엔지니어링의 기본 원칙은 “이해하지 못한 코드는 프로덕션에서 실행해서는 안 된다”는 것임
  • 이 원칙은 코드에 반드시 버그가 있어서가 아니라, 버그가 발생했을 때 어디서부터 봐야 할지 모르게 되기 때문에 유지보수성의 기준선이 됨
  • PR의 리뷰어 목록에는 coderabbitai[bot], claude[bot]이 있었고, 유일한 인간 리뷰어 alii는 “Awaiting requested review” 상태였음
  • Claude가 작성하고 Claude가 리뷰한 폐쇄 루프는 논리적으로 불가능한 일은 아니지만, 결과적으로 전체 코드베이스를 인간이 실제로 끝까지 읽지 않았다는 뜻이 됨

테스트 통과가 보장하지 못하는 것

  • 모든 플랫폼에서 테스트 스위트가 통과하더라도, 이는 알려진 동작과 알려진 경로의 올바름만 검증함
  • 테스트 스위트는 다음 영역을 충분히 보장하기 어려움
    • 에러 경로가 올바르게 처리되는지
    • 스트레스 상황의 경계 조건에서 어떤 동작을 하는지
    • 동시성 상황에서 상태 일관성이 유지되는지
    • 극단적 조건에서 메모리 모델이 의도와 맞는지
  • Jarred도 JS 경계를 다시 진입할 때의 메모리 문제는 Rust 컴파일러가 처리할 수 없고 여전히 인간에 의존한다고 인정한 것으로 정리됨
  • 문제는 인간에 의존해야 하는 그 부분을 인간이 리뷰하지 않았다는 점
  • AI의 코드 번역은 각 함수가 원본과 고립된 상태에서 동일하게 동작하도록 맞추는 국소적 의미 동등성에 가까움
  • 함수 사이의 전역 불변식, 테스트에 적히지 않고 원저자의 머릿속에만 있는 설계 제약은 AI 번역만으로 보장하기 어려움
  • 이런 제약은 현재 테스트에서는 드러나지 않다가 6개월 뒤 특정 프로덕션 부하에서 설명하기 어려운 충돌로 나타날 수 있음
  • 이는 Claude만의 문제가 아니라, 충분한 리뷰 없이 번역하는 모든 도구와 인간 프로그래머에게도 해당함
  • 6,755개 커밋 규모에서는 이런 위험이 크게 증폭됨

인수 이후 바뀐 위험 부담자

  • 초기 Bun은 Jarred가 스스로에게 베팅한 프로젝트였고, Zig 사용, 빠른 반복, 기술 부채 수용은 스스로 위험을 떠안는 스타트업 논리로 볼 수 있음
  • Bun이 대기업에 인수되고 실제 프로덕션 시스템에서 쓰이는 사용자 기반을 갖게 된 지금, 재작성의 위험 부담자는 Jarred가 아니라 프로덕션에서 Bun을 실행하는 엔지니어와 그 뒤의 사용자들로 바뀜
  • Jarred는 해당 버전이 아직 canary이고, 공식 릴리스 전 최적화와 정리 작업이 남아 있다고 말함
  • canary는 방어선이지만 인간 리뷰의 대체물은 아님
  • 최적화와 정리는 코드 품질의 문제이지, 유지보수자가 코드를 이해했는지의 문제를 해결하지 못함
  • 팀 누구도 전체를 완전히 읽지 않은 코드베이스는 테스트가 포괄적이거나 canary 기간이 길어도 유지보수자에게 내부 상태가 블랙박스로 남음
  • 이 문제는 향후 심각한 버그를 디버깅하는 현장에서 실제 고통으로 드러날 수 있음

Zig 문제 진단의 오류

  • Jarred가 제시한 이전 이유는 Zig 코드베이스에 use-after-free, double-free, 에러 경로의 메모리 누수가 많았다는 것임
  • 이 진단 자체는 맞지만, 여기서 “Zig가 작동하지 않는다”는 결론을 내리기는 어려움
  • 더 정확한 진단은 빠른 반복을 우선하는 상업 프로젝트에서 수동 메모리 관리의 인지 비용이 팀의 예산을 초과했다는 것임
  • 이는 Zig의 버그가 아니라, Zig의 설계 목표와 Bun의 비즈니스 모델 사이의 구조적 불일치로 볼 수 있음
  • Zig의 대상 사용자는 자신이 무엇을 하는지 알고, 최종적인 제어를 위해 비용을 지불할 의지가 있는 시스템 프로그래머임
  • TigerBeetle은 Zig로 사실상 메모리 버그가 거의 없는 데이터베이스를 작성했는데, 팀 문화와 프로젝트 성격이 Zig의 철학과 맞았기 때문으로 정리됨
  • Bun 팀 문화는 빠른 반복, 빠른 출시, 빠른 버그 수정에 가깝고, 이는 Zig가 요구하는 엄격한 메모리 규율과 근본적으로 긴장 관계에 있음
  • “우리 팀이 이 도구로 자주 실수한다”를 “이 도구가 부적합하다”로 해석하는 것은 귀인 오류에 가까움
  • 망치가 맞지 않았다고 해서 망치 자체의 잘못은 아니라는 비유가 사용됨

단기 전망과 장기 위험

  • 단기적으로는 재작성 버전이 대체로 괜찮을 가능성이 높음
  • 주요 경로는 테스트로 커버되고, canary 단계에서 명백한 문제가 드러나며, Rust 컴파일러 보장은 메모리 버그의 한 종류를 제거하기 때문임
  • 표면적으로는 모든 것이 정상처럼 보일 수 있음
  • 장기적으로는 인간이 완전히 읽지 않은 6,755개 커밋이 구조적 위험으로 남음
  • 6개월 뒤 기묘한 동시성 버그가 나타나거나, 특정 부하에서 경계 조건이 이상 동작을 유발하면, 디버깅 엔지니어는 누구도 진정으로 이해한 적 없는 시스템을 마주하게 됨
  • 이해된 적 없는 시스템이라는 말은 버그가 없다는 뜻이 아니라, 버그가 나타났을 때 왜 그런지 아무도 모른다는 뜻임
  • 이번 재작성의 실제 기술적 베팅은 Zig 대 Rust가 아니라, AI가 생성하고 리뷰되지 않은 코드를 프로덕션 환경에서 장기 유지보수할 수 있는지에 있음
  • 이 질문은 “테스트가 모두 통과한다”보다 복잡하고, “Rust의 메모리 안전성”보다 더 깊은 문제임
  • 결론은 “Zig가 기반을 만들고, Claude가 건물을 세웠으며, 인간 리뷰어는 아직 오는 중”이라는 비유로 압축됨
  • 이 건물이 얼마나 오래 거주 가능한지는 처음 누수가 발생했을 때 누군가가 설계도를 읽을 수 있는지에 달려 있음

댓글과 토론

Lobste.rs 의견들
  • “Bun을 Rust로 다시 쓰자”를 논하기 전에, Bun이 지금 위치에 온 건 Zig 덕분이라는 점을 말해야 함
    Bun 제작자 Jarred그렇게 말하고 있음. Zig가 Bun을 가능하게 했고, Oakland의 냄새나는 방에서 1년 동안 혼자 코딩하던 프로젝트가 JavaScript 생태계에서 가장 널리 쓰이는 도구 중 하나로 성장한 데에는 Zig의 공이 크다고 함
    또 Zig는 훌륭한 언어이고 Bun의 성공에 많은 빚을 졌지만, Ghostty나 Tigerbeetle 같은 다른 프로젝트들은 Bun이 겪은 안정성 문제를 겪지 않았다고도 말함

    • “Ghostty나 Tigerbeetle 같은 다른 프로젝트들은 Bun이 겪은 안정성 문제를 겪지 않았다”면, 왜 그런지 물어볼 만함
      보통 데이터베이스는 언어 런타임보다 안정성 과제가 훨씬 더 크기 때문임
  • 이 글은 LLM이 쓴 글 냄새가 많이 남

  • Zig의 대상 사용자가 “자기가 뭘 하는지 알고, 궁극의 제어권을 위해 대가를 치를 준비가 된 시스템 프로그래머”라면, Rust와 Swift 이후에 나온 언어 맥락에서 다시 등장한 C/C++식 과신처럼 보임
    Jarred가 옮기는 이유로 “Zig 코드베이스에 사용 후 해제, 이중 해제, 오류 경로의 메모리 누수가 너무 많았다”고 했다면, LLM에게 메모리 안전 버그를 열심히 찾게 하는 것만으로 메모리 안전하지 않은 언어를 실질적으로 안전하게 만들 수 있는지에 대한 자료점이 됨
    여기서는 LLM 회사조차 그 길을 택하지 않았음

  • “Claude가 쓴 코드, Claude가 검토한 코드라서 닫힌 고리가 논리적으로 불가능하진 않지만, 인간이 이 코드베이스 전체를 실제로 읽은 적은 없다는 뜻”이라는 말은 명백히 맞지 않아 보임
    사람이 작성한 Zig 코드베이스를 Rust로 기계적으로 번역했다면, 원래 코드를 이해하는 사람은 새 코드도 이해할 수 있음. APL로 옮기는 것도 아니고 둘 다 C 문법 전통의 절차형 언어임
    앞으로 LLM을 감독 없이 돌리면 코드가 점점 인간 감각에서 멀어질 수 있다는 논점은 열려 있지만, 지금 시점의 코드베이스는 백만 줄짜리 JavaScript 런타임이자 단일 바이너리 만능 도구가 가질 수 있는 정도로는 여전히 이해 가능해 보임
    “AI는 함수 단위의 지역적 의미 동등성만 맞추고, 함수 간 전역 불변식은 이해하지 못한다”는 문장은 LLM에 우호적인 방향으로도, 비판적인 방향으로도 이상함
    LLM은 각 함수가 원본과 동일하게 동작한다고 보장할 만큼 결정적이지 않음. 그런 보장에는 c2rust 같은 도구가 필요함. LLM은 원본처럼 보이는 코드를 번역할 수는 있지만, ((abc & 45) << 3) == 360((abc & 45) << 30) == 360으로 바꾸지 못하게 막는 건 컴파일러, 테스트 스위트, 어쩌면 LLM 기반 코드 리뷰의 확률적 탐지뿐임
    반대로 c2rust처럼 각 함수의 동일성을 보장하면서 LLM처럼 주석과 구조도 보존하는 번역기가 있다면, 그건 완벽한 번역기이고 백만 줄 코드베이스도 자동 이식할 수 있음. 컴파일러도 이런 특수한 사례로 볼 수 있고, Clang은 버그가 없진 않아도 사람들이 신뢰할 만큼 충분히 가까움. LLM이 Clang 수준의 신뢰도로 Zig나 C++를 Rust로 번역할 수 있다면 Chrome은 이달 말이면 순수 Rust가 됐을 것임
    또한 함수 간 불변식을 인코딩하는 게 바로 타입 시스템의 핵심임. Bun을 Rust로 다시 쓰는 이유 중 하나도 Rust 타입 시스템이 복잡한 불변식을 더 잘 표현할 수 있다는 점임. Anthropic이 전체를 어셈블리로 컴파일한 뒤 소스 코드를 태워버린 것도 아님

    • “사람이 작성한 Zig 코드베이스를 Rust로 기계적으로 번역했다면 원래 코드를 이해하는 사람은 새 코드도 이해할 수 있다”는 문장은 release fast에서는 통째로 최적화되어 사라질 듯함 :^)
      Bun은 Rust 이식 훨씬 전부터 바이브 코딩되어 왔음. AI를 꽤 빨리 받아들였고 Anthropic 인수 이후에는 거의 모든 커밋이 봇 작성임. Jarred도 주말 동안 AI에게 기능을 쓰게 해서 여러 기능을 추가했다는 트윗을 했음
    • Bun이 오래전부터 사람이 작성한 코드베이스가 아니라는 Kristoff의 지적은 별개로, Claude 이식이 기계적 번역일 거라고 가정하는 듯한데 실제로는 그렇지 않아 보임
      HTML Parsers in Portland는 Python HTML 파서의 여러 이식을 분석하면서, 핵심 알고리즘 중 하나가 각 이식에서 매우 다르게 구현됐다는 걸 보여줌. 각 경우 모두 기계적 이식이 가능했는데도 실제로는 그렇게 되지 않았음
      물론 올해 초의 사례이고 과정도 달랐지만, 이식 후 Bun 코드베이스에서 본 몇몇 조각도 비슷한 문제를 겪는 것처럼 보임
    • “사람이 작성한 Zig 코드베이스를 Rust로 기계적으로 번역했다면 원래 코드를 이해하는 사람은 새 코드도 이해할 수 있다”는 말 자체는 맞음
      하지만 “LLM은 각 함수가 원본과 동일하게 동작한다고 보장할 만큼 결정적이지 않다”는 점은, 결국 인간이 코드베이스 전체를 실제로 읽지 않았다는 결론으로 이어짐
  • “모든 테스트가 통과한다”의 한 예: https://github.com/oven-sh/bun/…

  • “이해하지 못하는 코드는 프로덕션에서 실행하면 안 된다”는 원칙을 요즘 많이 생각하고 있음
    커리어가 꽤 진행됐지만 일부러 관리직으로 가지 않았고, 프로그래밍 경력도 점점 스택 아래로 내려가는 쪽이었음. 실제 프로그램 자체를 깊게 이해하는 걸 좋아하기 때문임. 기능을 출시하고 사용자의 삶을 낫게 만드는 것도 매우 중요하지만, 프로그래밍에서 큰 내적 보상 중 하나는 실제 시스템에 대한 참인 사실을 배운다는 느낌임
    나 같은 사람에게는 인간이 프로그램의 모든 줄을 이해해야 한다는 게 공리처럼 느껴짐. 그런데 조직도상 내 매니저는 내가 유지보수하는 프로그램에 책임이 있음. 그는 훌륭한 매니저이고 마이크로매니지하지 않기 때문에, 팀이 출시하는 소프트웨어의 모든 줄을 당연히 이해하지 못함. 사실 코드를 거의 읽어봤는지도 모르겠음. 그러면 그는 이 원칙을 어기고 있는 셈임
    “부하 직원이 작성해서 내가 이해하지 못하는 코드”와 “내 AI가 작성해서 내가 이해하지 못하는 코드” 사이에 의미 있는 차이가 있는지 고민 중임
    1번은 괜찮은데 2번은 찜찜함. 차이는 그 코드에 대해 책임지는 인간이 있느냐뿐일까? 탓할 수 있는 누군가가 있느냐일까? 그게 내가 느끼는 강한 도덕적 감각을 정당화하기에 충분한지는 아직 모르겠음
    이 강한 감정이 좋은 엔지니어링에 필수인 게 아니라 개인적 미감에 가깝지 않을까 걱정됨. 각자 취향은 가질 수 있지만, 그게 전부라면 이 일의 이 측면이 앞으로 덜 즐거워질 거라고 예상해야 할 듯함. 결국 관리직으로 밀려나는 셈인데, 내 부하 직원들이 봇인 셈임

  • “Zig는 작은 팀이 가비지 컬렉터와 무거운 런타임 없이 고성능 JS 런타임을 빠르게 프로토타이핑할 수 있게 했다”고 하지만, 다른 주요 런타임인 Node와 Deno도 같은 일을 하고 있음
    둘 다 가비지 컬렉터 없는 언어인 C++와 Rust로 JS 엔진을 감쌈. V8이나 JSC 자체가 실제로 가비지 컬렉터를 함께 배포하는지는 잘 모르겠지만, 그건 핵심에서 벗어남

  • Bun 저장소 전체가 디스토피아처럼 느껴짐. 봇들이 서로 대화하면서 말도 안 되는 PR을 만들고 있음
    예: https://github.com/oven-sh/bun/issues/30766

  • 이게 “완료”로 간주된 속도는 꽤 충격적이지만, 글이 단단한 증거 없이 묘사하는 것처럼 움직이는 열차 사고라고 보이진 않음
    “6개월 뒤 이상한 동시성 버그가 나타나고, 특정 부하에서 어떤 경계 조건이 비정상 동작을 유발하면, 디버깅하는 엔지니어는 누구도 진정으로 이해한 적 없는 시스템을 마주하게 된다”는 건 순전한 추측이고 사실이 제시되지 않았음
    언어 이식은 LLM에게 잘 맞는 영역이고, 기반 코드도 많은 인간이 이해하고 있었음. 단순한 언어 이식이 왜 갑자기 진단 가능성을 되돌릴 수 없게 망가뜨린다는 건지 모르겠음