---
title: "Zig 빌드 시스템 대수술…빌드 러너 쪼개고 증분 빌드 밀리초대로 간다"
published: 2026-05-30T08:38:28.000Z
canonical: https://jeff.news/article/3447
---
# Zig 빌드 시스템 대수술…빌드 러너 쪼개고 증분 빌드 밀리초대로 간다

Zig 개발 로그에서 빌드 시스템이 configurer와 maker 프로세스로 분리되는 큰 변경이 소개됐다. `zig build -h` 기준 평균 실행 시간이 150ms에서 14.3ms로 줄었고, 새 ELF 링커는 Zig 컴파일러 자체를 LLVM·LLD 포함 상태로 빌드할 수 있는 단계까지 올라왔다.

## 빌드 시스템을 configurer와 maker로 쪼갬

- Zig 빌드 시스템에 큰 구조 변경이 들어감. 핵심은 `build.zig`를 실행하는 프로세스와 실제 빌드 그래프를 수행하는 프로세스를 분리한 것임
  - 예전에는 `build.zig` 파일과 빌드 시스템 구현 전체가 하나의 거대한 디버그 모드 프로세스로 컴파일됨
  - 이제 `build.zig`는 작은 configurer 프로세스로 컴파일되고, 빌드 그래프를 만든 뒤 바이너리 설정 파일로 직렬화함
  - 실제 빌드 실행은 release 모드로 컴파일된 maker 프로세스가 맡음

- 이 변경의 목적은 노골적으로 `zig build`를 빠르게 만드는 것임
  - 사용자의 `build.zig` 로직이 바뀔 때마다 빌드 시스템 전체를 다시 컴파일하지 않아도 됨
  - 이전 설정을 재사용할 수 있으면 `build.zig` 로직 자체도 다시 돌리지 않음
  - 빌드 그래프를 실행하는 maker는 최적화된 release 모드로 돌아감

> [!IMPORTANT]
> `zig build -h` 벤치마크에서 평균 wall time이 150ms에서 14.3ms로 줄었다. 수치로 보면 90.4% 감소라서, 체감상 “좀 빨라짐”이 아니라 거의 다른 명령처럼 느껴질 변화임.

- 공개된 벤치마크가 꽤 세다
  - 기존 master 기준 `zig build -h`는 평균 150ms, peak RSS 84.8MB, CPU cycles 5억9300만 정도였음
  - 새 브랜치에서는 평균 14.3ms, peak RSS 78.5MB, CPU cycles 2410만으로 줄었음
  - instructions도 9억9500만에서 4370만으로 95.6% 감소함

- 왜 이렇게 차이가 크냐면, 이전에는 도움말을 보는 명령에서도 `build.zig` 로직이 매번 실행됐기 때문임
  - 새 구조에서는 캐시된 직렬화 설정을 재사용할 수 있음
  - `--watch`, `--fuzz`, `--webui` 같은 기능이 늘어나도 빌드 시스템 자체가 계속 커지는 부담을 줄이는 방향임

## 호환성 변화와 도구 생태계 영향

- 대부분은 API 관점에서 깨지는 변경이 아니라고 하지만, 빌드 스크립트에서 인자를 다루던 코드는 손봐야 할 수 있음
  - 기존 패턴은 `if (b.args) |args| { run_cmd.addArgs(args); }` 형태였음
  - 새 방식은 `run_cmd.addPassthruArgs();`를 쓰는 쪽으로 바뀜
  - 빌드 스크립트가 전달 인자를 관찰할 수 없게 되는 대신, 인자가 바뀔 때마다 빌드 스크립트를 다시 컴파일할 필요가 줄어듦

- ZLS 같은 서드파티 도구도 이득을 볼 가능성이 있음
  - 빌드 러너를 따로 흉내 내거나 포크해서 유지하는 대신, 직렬화된 설정 파일을 읽는 방향이 열림
  - 빌드 시스템의 내부 상태가 더 명확한 산출물로 남는다는 점에서 도구 개발자에게 의미가 있음

## 새 ELF 링커와 증분 빌드

- 같은 개발 로그에서 새 ELF 링커도 꽤 큰 진전을 보임
  - Zig 0.16.0에서 처음 들어간 새 ELF 링커는 아직 기본값이 아니고 `-fnew-linker`로 켜야 함
  - 초기에는 외부 라이브러리나 libc 없이 Zig-only 코드 정도만 링크할 수 있었음
  - 최신 PR 기준으로는 LLVM과 LLD 라이브러리를 켠 self-hosted Zig 컴파일러를 빌드할 수 있는 단계까지 왔다고 함

- 헤드라인은 빠른 증분 컴파일임. x86_64 리눅스에서는 외부 라이브러리와 C 소스를 링크하는 프로젝트에서도 증분 재빌드가 가능해짐
  - Andrew Kelley의 테트리스 클론에서 동작하는 데모를 언급함
  - Zig 컴파일러 자체도 `-fincremental --watch`로 첫 빌드 36초 이후 재빌드가 244ms, 228ms, 288ms, 283ms 수준으로 떨어지는 예시가 나옴

> [!WARNING]
> 새 ELF 링커는 아직 Zig 코드용 DWARF 디버그 정보 생성을 지원하지 않음. print 디버깅 위주의 빠른 루프에는 매력적이지만, 디버거 중심 워크플로라면 이 빈칸을 감안해야 함.

- Zig 0.17.0이 몇 주 안에 나올 예정이라는 맥락도 중요함
  - master 브랜치를 쓰는 x86_64 리눅스 사용자라면 지금 테스트해보고 이슈를 올려달라는 요청이 있음
  - 릴리스만 따라가는 사용자도 곧 0.17.0에서 이 변화를 만나게 될 가능성이 큼

---

## 기술 맥락

- 이번 Zig 변경은 빌드 시스템을 단순 최적화한 게 아니라 실행 모델을 바꾼 거예요. 왜냐하면 기존 구조에서는 사용자의 `build.zig`와 빌드 시스템 구현이 한 덩어리로 묶여 있어서, 작은 명령도 생각보다 많은 코드를 다시 실행해야 했거든요.

- configurer와 maker를 나눈 이유는 설정과 실행의 성격이 다르기 때문이에요. `build.zig`는 개발자가 작성한 로직이라 자주 바뀔 수 있지만, 빌드 그래프를 실행하는 엔진은 Zig 버전이 같으면 대부분 재사용할 수 있어요. 그래서 설정은 직렬화하고, 실행기는 전역 캐시에 두는 쪽이 유리해요.

- 새 ELF 링커 쪽은 더 깊은 통합을 노리는 흐름이에요. 외부 링커에 맡기면 일반적인 링크는 가능하지만, Zig가 원하는 밀리초 단위 증분 재빌드까지 세밀하게 제어하기 어렵거든요. 자체 링커를 키우는 이유가 여기서 나와요.

- 다만 아직 완성형은 아니에요. 특히 DWARF 디버그 정보가 빠져 있으면 디버거 기반 개발에는 제약이 생겨요. 그래서 지금은 “프로덕션 기본값”이라기보다 빠른 피드백 루프를 원하는 사용자에게 먼저 열어두고 피드백을 받는 단계로 보는 게 맞아요.

## 핵심 포인트

- Zig 빌드 시스템이 build.zig 설정 단계와 빌드 그래프 실행 단계를 분리함
- 직렬화된 설정 파일과 전역 캐시를 활용해 반복 빌드에서 불필요한 build.zig 재실행을 줄임
- `zig build -h` 벤치마크에서 평균 wall time이 150ms에서 14.3ms로 90.4% 감소함
- 새 ELF 링커는 x86_64 리눅스에서 외부 라이브러리와 C 소스를 포함한 증분 재빌드를 지원하기 시작함
- 주요 호환성 변경으로 `b.args` 관찰 방식 대신 `run_cmd.addPassthruArgs()` 사용이 제시됨

## 인사이트

Zig의 이번 변경은 언어 기능보다 개발 루프 자체를 줄이는 쪽에 무게가 있다. 컴파일러·빌드 시스템·링커를 한 몸처럼 가져가는 Zig의 설계가 장점으로 드러나는 사례라, 빌드 도구를 만드는 사람에게도 꽤 볼 만하다.
