라떼군 이야기
Zig의 과감한 행보: io_uring 통합, Kernel32 우회, 그리고 C 없는 libc
TL;DR Zig가 std.Io에 io_uring(리눅스)과 GCD(맥) 구현을 추가하여 코드 변경 없이 비동기 I/O를 지원합니다. 또한 윈도우에서 Kernel32.dll을 우회하여 ntdll을 직접 호출함으로써 성능을 최적화하고, C libc를 Zig로 재작성하여 의존성을 제거하고 있습니다.
시스템 프로그래밍 언어 Zig가 0.16.0 릴리스를 앞두고 매우 흥미로운 기술적 진보를 공개했습니다. 단순히 기능을 추가하는 것을 넘어, OS의 커널 API를 다루는 방식과 패키지 관리의 근본적인 워크플로우를 개선하고 있습니다. 특히 비동기 I/O 처리 방식의 변화와 윈도우 시스템 호출 최적화는 저수준 성능 최적화에 관심 있는 개발자라면 반드시 주목해야 할 내용입니다.
핵심 내용
첫째, std.Io에 io_uring(Linux)과 Grand Central Dispatch(macOS) 구현이 추가되었습니다. 이는 사용자 공간 스택 스위칭(파이버/그린 스레드)을 통해 구현되어, 개발자는 동기 코드처럼 작성하더라도 내부적으로는 고성능 비동기 I/O로 동작하게 됩니다.
둘째, 패키지 관리자가 개선되어 프로젝트 루트에 의존성을 캐싱함으로써 오프라인 빌드가 용이해졌습니다. 특히 zig build --fork=[path] 옵션이 추가되어, 의존성 라이브러리의 코드를 로컬에서 수정하고 즉시 테스트하는 워크플로우가 획기적으로 간편해졌습니다.
셋째, 윈도우에서 Kernel32.dll을 우회하고 ntdll.dll을 직접 호출하는 ‘Native API’ 우선 정책을 강화했습니다. 이를 통해 불필요한 힙 할당을 줄이고, 에러 처리를 명확히 하며, 비동기 파일 I/O(APC 루틴 활용)의 효율성을 높였습니다.
넷째, C 언어로 작성된 libc 함수들을 Zig로 직접 재작성하여 대체하고 있습니다. 이는 C 의존성을 제거할 뿐만 아니라, 컴파일러가 libc 경계를 넘어 최적화(LTO 유사 효과)를 수행할 수 있게 만듭니다.
기술적 인사이트
이 업데이트에서 가장 주목할 점은 Zig의 ‘수직 통합’ 전략입니다. 보통의 언어들이 OS가 제공하는 표준 래퍼(Kernel32, libc 등)를 그대로 사용하는 반면, Zig는 성능과 정확성을 위해 이 중간 계층을 걷어내고 있습니다. 특히 io_uring을 언어 런타임 레벨에서 투명하게 지원하려는 시도는 Rust의 async/await가 가진 ‘함수 색깔 문제(Function Coloring Problem)‘를 피하면서도 고성능을 달성하려는 야심 찬 접근입니다. 또한 ntdll 직접 호출은 유지보수 난이도는 높지만, 윈도우 시스템 프로그래밍의 고질적인 오버헤드를 언어 차원에서 해결하겠다는 강력한 의지를 보여줍니다.
시사점
시스템 개발자들은 앞으로 복잡한 비동기 런타임을 직접 관리하지 않고도 최고의 I/O 성능을 낼 수 있게 될 전망입니다. 또한 --fork 기능은 오픈소스 기여나 디버깅 과정의 마찰을 크게 줄여 생태계 활성화에 기여할 것입니다. 장기적으로 Zig로 작성된 애플리케이션은 C/C++로 작성된 동급 프로그램보다 더 가볍고(libc 제거), 더 빠르며(커널 직통 호출), 배포하기 쉬운(정적 링크) 형태가 될 가능성이 높습니다.
Zig는 ‘기존의 것을 잘 쓰는 것’을 넘어 ‘더 나은 근본을 만드는 것’으로 나아가고 있습니다. 과연 Zig 팀이 방대한 OS API와 libc의 재구현을 안정적으로 유지보수할 수 있을까요? 이들의 기술적 고집이 시스템 프로그래밍의 새로운 표준이 될지 지켜보는 것은 매우 흥미로운 일이 될 것입니다.