함수형 시스템 언어 Roc의 컴파일러가 기존 Rust 구현의 구조적 결함을 해결하고 성능 및 개발 경험을 개선하기 위해 약 30만 줄의 코드를 Zig 언어로 재작성하는 대규모 프로젝트를 487일 만에 성공적으로 마쳤습니다. 이 재작업을 통해 Roc 컴파일러는 기존 버전과 기능적으로 동등한 수준에 도달했으며, 올해 하반기 첫 정식 번호 릴리스인 0.1.0 버전을 목표로 하고 있습니다.
이번 재작성의 핵심 동기는 기존 Rust 구현의 구조적 결함 해결과 더불어, 빌드 시간 단축, 세분화된 메모리 할당 및 데이터 배치 제어, 컴파일러 개발에 더 적합한 생태계, 그리고 메모리 비안전 코드 검사 기능 강화였습니다. 특히 Zig 0.17.0의 증분 빌드는 약 46만 줄의 코드를 35ms 만에 다시 빌드할 수 있을 정도로 빠른 속도를 자랑합니다. 새로운 컴파일러는 개발자에게 핫 코드 로딩(코드 수정 시 다음 요청부터 자동 적용), 재현 가능한 크로스 컴파일(어떤 빌드 시스템에서도 동일한 출력 바이너리 생성), 패턴 매칭 내 문자열 보간 지원 등 향상된 개발 경험을 제공하며, WASM-4 게임 'Rocci Bird'의 WebAssembly 바이너리 크기를 기존의 절반 이하인 31KB로 줄이는 성과도 거두었습니다.
Zig를 선택한 주요 이유 중 하나는 Rust의 `unsafe` 블록 사용에 대한 접근 방식과 차이점 때문입니다. Roc 컴파일러는 기계어를 생성하는 특성상 메모리 비안전 작업이 불가피하게 많았는데, Rust는 `unsafe` 사용을 최소화하고 격리하는 반면, Zig는 메모리 비안전 코드를 올바르게 다루기 위한 기능을 더 적극적으로 제공한다는 판단이 작용했습니다. 비록 Rust의 보로우 체커(borrow checker)가 특정 유형의 `use-after-free` 버그를 방지할 수 있었겠지만, Roc 팀은 대부분의 메모리 손상 버그가 컴파일러 내부 로직이 아닌 잘못 생성된 기계어(오컴파일)에서 발생했으며, Zig의 추가 검사 기능이 본질적으로 비안전한 코드에 더 유용하다고 결론 내렸습니다. 이처럼 언어 선택은 프로젝트의 특정 요구사항과 개발 문화에 따라 달라질 수 있음을 보여주는 사례입니다.
이번 재작업은 단순히 언어를 바꾸는 것을 넘어, 컴파일러의 구조와 기능을 대폭 개선하는 과정이었습니다. 이는 Roc이 참조 카운팅 기반 자동 메모리 관리, Perceus 최적화, 람다 집합 특수화를 통한 다형적 비함수화 등 고유한 메모리 관리 및 최적화 기법을 사용하기 때문에 더욱 복잡했습니다. 이러한 대규모 재작성은 컴파일러 프로젝트에서 자체 호스팅(self-hosting) 등을 위해 흔히 발생하는 일이며, Roc 팀은 이번 재작성을 통해 얻는 이점이 알려진 비용보다 크다고 판단했습니다. 이는 고성능 시스템 언어 개발에 있어 언어 선택과 아키텍처 설계가 얼마나 중요한지, 그리고 때로는 과감한 재작성이 장기적인 성공을 위한 필수적인 단계가 될 수 있음을 시사합니다.