Zig에서 Rust로, 그리고 다시 Zig로 돌아오며 느낀 점과 그 이유를 돌아본다.
Zig에서 Rust로, 그리고 다시 Zig로
2026-06-10 · 9분 · #computing
Zig는 인기를 얻고 있다. 아직 Rust나 Go는 물론이고 C가 차지한 공간까지 빼앗지는 못했지만, 몇몇 주요 프로젝트와 셀 수 없이 많은 작은 프로젝트들에 채택되었다. 그런 만큼 미래에 중요한 언어가 되어 가고 있다. 나는 몇 년 동안 Zig에 관심을 가져왔기 때문에, 오늘날 이 언어를 다시 돌아보고 지금은 어떻게 느끼는지 살펴보기로 했다.
나는 2020년에 한 프로그래밍 멘토를 통해 처음 Zig를 접했다. 그들은 컴파일 시간 코드 실행과 아름다우면서도 단순한 추상화 형태를 갖춘 이 작고 새로운 언어에 큰 열정을 가지고 있었다. 나도 한번 살펴보기로 했다.
당시 나는 여전히 C를 배우는 데 깊이 빠져 있었다. 컴퓨터를 강하게 통제할 수 있다는 점은 즐거웠지만, 시대에 뒤떨어진 추상화와 더 나쁜 도구 환경 때문에 답답함을 느끼고 있었다. Zig는 새롭고 불안정하긴 했지만 C의 대체재 로 약속되고 있었다. 그것이 나를 사로잡았다. 다음 세대의 언어를 배울 수 있는데 왜 C를 배워야 할까?
나는 Andrew Kelley의 강연을 더 많이 보았다. Software Should Be Perfect는 내게 큰 영향을 주었다. 그것은 내가 프로그래밍 언어, 그리고 더 일반적으로는 소프트웨어가 어떤 모습이어야 하는지에 대한 관점을 형성했다. 그 강연에서 Andrew는 실패 가능성이 있고 명시적인 메모리 할당, 숨겨진 제어 흐름의 부재, 그리고 보편적인 재사용 가능성의 중요성을 강조했다. 그것들은 모두 내가 이후 어떤 프로그래밍 언어에서든 찾기 시작한 가치였다.
그래서 나는 Zig로 옮겨 갔다. 장난감 프로그래밍 언어를 만들고, 문예적 프로그래밍 도구를 실험하고, 웹 서버를 가지고 놀았다. Zig로 작업하는 것은 즐거웠다. C보다 더 좋게 느껴졌지만 위험한 함정은 없었다.
Zig는 계속 내 코드를 깨뜨렸다. 나는 그 끊임없는 변화에 지쳤다. 나는 학생이었고, 내 코드를 언어의 최신 버전에 맞게 계속 갱신할 시간이 많지 않았다. 그때는 anyzig가 같은 시스템에서 여러 Zig 버전을 다루는 일을 아주 쉽게 만들어 주기 전이었다. 나는 종종 몇 달씩 특정 프로젝트를 손대지 않고 지냈다. 그러다 다시 돌아오면, 다시 동작하게 만들기 위해 내가 이해하지 못하는 대규모 리팩터링을 해야 했다.
Zig 생태계도 미성숙했다. 나는 새 프로그래머였기 때문에 모든 것을 혼자 구현할 기술이 없었다. 무엇이든 쓸 만한 라이브러리는 거의 없었고, 나를 가르쳐 줄 예제도 드물었다. 표준 라이브러리는 계속 바뀌었다. 그 추상화가 어떻게 작동하는지 이해했다고 생각할 때마다 또 바뀌었다. 기본 문서가 불안정했다는 점도 도움이 되지 않았다.
그래서 나는 Rust로 떠났다. 그 시점에서 Rust는 이미 여러 해 동안 안정화되어 있었고, 강력한 생태계를 갖추고 있었다. 배우는 과정은 고통스러웠고, 몇 번이나 포기하고 싶었지만, 일단 배우고 나니 제대로 작동했다. 그 점은 나에게 매우 소중했다. 내가 필요로 하는 표현력을 갖춘 빠른 저수준 프로그래밍 언어이면서도, 불안정성의 대가를 치르지 않아도 되었다. 또한 그것은 내장된 검사 장치가 더 적은 언어들에서도 잘 통하는 정신적 메모리 모델을 발전시키도록 나를 강제했다.
장점으로는, 코드가 panic하지 않는 한, 숨겨진 제어 흐름이나 가비지 컬렉터 없이도 재사용 가능한 코드를 작성할 수 있었다. 메모리 할당을 숨기고 C와의 작업을 어렵게 만들기는 했지만, Zig가 왜 매력적이었는지에 거의 한 바퀴를 돌아 다시 닿게 해 주었다.
나는 Rust를 사랑한다. 지금도 그 언어로 작업하는 것을 즐긴다. 그 추상화는 내게 기쁨을 준다. 안타깝게도, 프로젝트가 나아가고 있는 몇몇 방향은 걱정스럽다.
Rust도 여전히 완벽하지는 않다. 프로그래밍 언어에서 내가 찾고 있던 많은 것들을 제공하지만, 내가 만들고 싶은 재사용 가능한 프로그램을 만드는 데 가장 이상적인 것은 아니다. FFI는 어렵다. 크로스 컴파일은 성가시다. 숨겨져 있고 실패하지 않는 메모리 할당이 나를 따라다닌다. LLVM에 묶여 있기 때문에, C만큼 많은 플랫폼을 지원하기까지는 아주 오랜 시간이 걸릴 것이고, 어쩌면 영영 불가능할지도 모른다.
게다가 그 거버넌스도 여전히 마음에 걸린다. Rust에는 몇몇 거대한 기업 foundation members가 있고, 그들은 거의 확실하게 Rust가 개발되는 방식에 영향을 미친다. 세계에서 가장 큰 기업들이 해마다 각각 수십만 달러를 주고 있다면, 아마 그들을 불편하게 만들고 싶지는 않을 것이다.
그럼에도 불구하고, 오픈 소스 공동체를 vibecoding의 재앙이 덮치기 전까지는 이런 점들을 받아들일 수 있었다. 끔찍하게도, 많은 소프트웨어 프로젝트들이 LLM이 생성한 코드를 받아들이고 있었다. 나는 LLM이 개발자들 사이에서 인기가 없다고 생각했었다. 그것을 사용하는 사람들은 고용주에게 강요당한 사람들뿐이라고 여겼다.
이 일이 벌어지자, 유지보수자와 사용자 모두 LLM 정책을 작성하거나 요구했다. Zig는 그것들을 프로젝트에서 완전히 금지했다. 반면 Rust는 시간을 끌었다. 몇 차례 의견 수렴을 했고 공동체의 전반적 정서는 반LLM 쪽이었지만, 아직 공식 정책을 만들 준비는 되어 있지 않았다.
그들이 마침내 제안을 내놓았을 때, 여기에는 악명 높은 조정 정책이 포함되어 있었다.
이 PR에 대한 어떤 댓글도 다음 주제를 언급해서는 안 된다:
- LLM의 장기적인 사회적 또는 경제적 영향
- LLM의 환경적 영향
- LLM 출력물의 저작권 상태와 관련된 모든 것
- LLM을 사용하는 사람들에 대한 도덕적 판단
이후 반발 끝에 이것은 삭제되었지만, 애초에 이런 일이 있었다는 사실 자체가 앞으로 Rust 프로젝트를 신뢰하는 마음을 잃게 만들었다. 나는 그 언어를 사랑하지만, 거버넌스에는 좌절감을 느낀다.
정책 자체는 괜찮다. 그것은 거의 전적으로 LLM을 제한한다. 대부분의 허접한 산출물을 줄여 준다. Zig의 정책만큼 강력하지는 않지만, 실용적으로 쓸 수는 있다. 하지만 이 모든 경험은 내가 몇 년 만에 처음으로 프로그래밍 언어로서의 Zig를 진지하게 탐구하게 만들었다.
내가 처음 알아차린 것은 이 언어가 여전히 불안정하다는 점이다. 웹에서 찾은 0.16.0용 예제들로 시작해 보려고 했을 때, 그것들이 이미 오래되었다는 사실을 알게 되었다. Zig에서 생산적으로 일하는 가장 좋은 방법은 표준 라이브러리 소스의 사본을 곁에 두고 그것에 익숙해지는 것이라는 점도 알게 되었다.
나는 Zig의 안정성에 대해 어떤 환상도 품고 있지 않다. Zig 0.17.0은 곧 출시될 것이다. 그리고 그것은 모든 프로젝트의 빌드 시스템을 깨뜨릴 것이다. 유지보수자들이 안정화를 향해 방향을 옮기려 하고 있으며, 이런 파괴적 변경이 그 과정의 일부라는 점도 나는 이해하고 있다.
다행히도, 2020년 이후 언어 자체는 그렇게까지 많이 바뀌지 않았다. 내 직감 대부분이 여전히 유효하다는 것을 알게 되었다. 라이브러리의 몇몇 부분은 다시 손질되었지만, 코드는 읽기 쉽고 나는 금방 길을 찾을 수 있었다. 오늘날의 Zig 코드도 6년 뒤에 똑같이 알아볼 수 있으리라고 나는 확신한다.
또 하나 눈에 띈 점은 Zig에 이제 패키지 관리자가 있다는 것이다. 내가 떠날 무렵에는 개발 중이었던 것으로 기억한다. 당시에는 의존성 관리를 위해 git submodule을 사용했던 기억이 난다. 내장 도구는 훨씬 더 낫다. 프로젝트는 git과 tarball을 통해 의존성을 정의할 수 있다. vendoring도 수고 없이 된다. 모든 것이 그냥 작동한다.
여전히 방대한 생태계가 있는 것은 아니지만, 애초에 그것은 Zig가 지향하던 바가 아니었다. Zig 프로젝트를 위한 공식 패키지 레지스트리가 없는 데에는 이유가 있다. 우리는 또 다른 NPM이나 crates.io가 필요하지 않다. 적어도 내게는, Zig가 완벽한 균형을 찾아냈다.
나는 Zig가 Rust와 같은 메모리 안전성 보장을 제공하지 않는다는 점을 알고 있다. 안타깝지만 그것은 단순성을 위해 그들이 택한 절충이다. Rust의 affine type이 지닌 복잡성은 그 안전성 이점만큼의 가치가 없었다.
그렇다고 해서 그들이 안전성을 포기했다는 뜻은 아니다. Zig는 unsafe Rust보다 더 안전하다. 그래서 어차피 unsafe Rust를 써야 하는 상황이라면, Zig가 더 나은 선택일 수도 있다.
Zig는 또한 언어를 더 안전하게 만들기 위해 노력하고 있다. 그들의 접근법은 코드의 unsafe 구역보다는 릴리스 모드에 초점을 맞춘다. 현재 Zig의 ReleaseSafe 모드는 assert가 실패하면 충돌하고, 모든 메모리를 초기화한다. 그러나 Andrew Kelley는 이것을 더 밀어붙이는 데 관심이 있다. 이를테면 Fil-C와 비슷한 것을 포함한 ReleaseSafe를 배포하는 식이다. 이것이 Rust의 컴파일 시간 메모리 안전성을 제공하지는 않겠지만(unsafe를 피한다고 가정하더라도), 그렇다고 해서 일부가 말하듯 파멸의 악순환이 되는 것은 아니다.
메모리 안전성은 하나의 스펙트럼이다. 모든 상황에서 가장 잘 작동하는 단 하나의 메모리 안전성 접근법이 있는 것은 아니다. Zig의 방식은 ReleaseSafe를 런타임에서 가능한 한 안전하게 만들고, 이후 테스트와 퍼징을 통해 정확성을 보장하는 것이다. 검사되지 않은 불법 동작은 그 단계에서 발견되어야 한다. 그 정확성이 입증된 뒤에는, 다른 릴리스 모드의 바이너리를 안전하게 배포할 수 있어야 한다.
이 접근법은 Rust 모델과 비교했을 때 몇 가지 단점이 있지만, 특히 Zig가 Rust로서는 꿈꾸기만 할 수 있는 단순성을 추구한다는 점을 생각하면, 결코 엄밀히 열등하다고만 할 수는 없다. 프로그래밍 언어는 많고, 당신은 자신의 사용 사례에 가장 잘 맞는 것을 고를 수 있다. 컴파일 시간 메모리 안전성이 복잡한 타입 시스템과 긴 컴파일 시간의 대가를 치를 만큼 가치 있다면, 그렇게 하면 된다. 그러나 모든 상황의 모든 사람에게 그런 것은 아니다.
Zig의 메모리 안전성 모델은 assertion에 대한 철학으로도 확장된다. Zig는 ReleaseFast에서 assertion을 비활성화하는 대신, 당신의 assertion이 올바르며 그 경로들이 도달 불가능하다는 것을 입증하는 데 필요한 테스트를 당신이 수행했다고 신뢰하고, 그에 따라 Zig가 코드를 최적화할 수 있게 한다.
Zig는 완벽함을 요구하지만, 그 완벽함에 도달할 도구도 제공한다.
그러니 이제 표준 라이브러리와 릴리스 변경 기록을 손에 쥔 채, 나는 Zig로 내가 마주하는 어떤 소프트웨어 문제든 맞설 준비가 되어 있다. 더 저수준의 세부 사항을 다루고 싶지 않을 때는 내 선호하는 스크립트 언어를 찾겠지만, 미래 소프트웨어의 주력 엔진은 Zig가 될 것이다.
내가 Zig에 계속 머무르지 않을 가능성도 있다. 안정성이나 타입 시스템이 필요할 때는 Rust를 선택할 수도 있다. Zig의 접근법에 대해 내 생각이 완전히 바뀔 가능성도 있다. 여러 언어는 함께 존재할 수 있고, 또 그래야 한다.
하지만 Zig는 내게 공명하는 소프트웨어 비전을 대표한다. 소프트웨어 품질을 무시함으로써가 아니라, 오히려 그것을 받아들임으로써 사용자에게 집중하는 소프트웨어다. 사람들은 신뢰할 수 있고 강력한 소프트웨어를 누릴 자격이 있다. 이것은 LLM의 시대에는 특히 더 그렇다. 그 시대에는 세심하게 만들어진 소프트웨어가 점점 드물어지고, 사람들은 점점 더 나빠지는 허접한 결과물을 받아들이라는 압력을 받고 있다.