---
title: "Zig, 패키지 관리 로직을 컴파일러에서 빌드 시스템으로 옮겼다"
published: 2026-07-04T16:30:10.000Z
canonical: https://jeff.news/article/4679
---
# Zig, 패키지 관리 로직을 컴파일러에서 빌드 시스템으로 옮겼다

Zig가 패키지 fetch, HTTP/TLS, Git, 압축 처리, build.zig.zon 파싱 같은 패키지 관리 기능을 컴파일러 실행 파일에서 빼서 빌드 시스템의 maker 프로세스로 옮겼다. 덕분에 컴파일러를 다시 빌드하지 않고도 해당 로직을 패치할 수 있고, build server와 ZLS 연동을 막던 프로세스 구조 문제도 풀리는 방향으로 갔다.

- Zig가 패키지 관리 기능을 컴파일러 본체에서 빼서 빌드 시스템으로 옮김
  - 이동한 하위 명령은 `zig build`, `zig fetch`, `zig init`, `zig libc` 쪽 로직임
  - 패키지 fetch, HTTP 클라이언트, 네트워킹, TLS, crypto, Git 프로토콜, xz/gzip/zstd/flate/zip 처리, `build.zig.zon` 파싱과 검증이 컴파일러 실행 파일 밖으로 빠짐
  - 이제 이 기능들은 컴파일러를 다시 빌드하지 않고도 소스 형태로 패치하고 실험하기 쉬워짐

- 바이너리와 실행 모드 측면에서도 변화가 있음
  - LLVM 없는 ReleaseSmall 기준 Zig 실행 파일 크기가 14.1MiB에서 13.5MiB로 줄어서 약 4% 감소함
  - 패키지 관리의 네트워킹 작업은 maker 실행 파일이 ReleaseSafe 모드로 컴파일되기 때문에 안전성 검사가 켜진 상태로 돈다
  - crypto와 파일 해싱은 배포 바이너리에서 기대하기 어려운 희귀 CPU 명령까지 호스트에서 활용할 수 있게 됨

- 이 변경의 진짜 배경은 ZLS와 build server protocol 쪽에 있음
  - 이전 구조에서는 `zig build` 아래에 사용자의 `build.zig` 로직과 빌드 시스템 구현이 섞여 있었음
  - 이후 configurer와 maker를 분리했지만, 패키지 관리가 여전히 상위 `zig build` 쪽에 있어서 build.zig가 바뀌면 maker가 종료되어야 했음
  - 이제 maker가 build system과 package manager를 함께 들고 있고, configurer가 그 아래에서 사용자 build.zig 로직을 실행하는 구조가 됨

```mermaid
sequenceDiagram
    participant 사용자 as 사용자
    participant 지그 as Zig 컴파일러
    participant 메이커 as 메이커 프로세스
    participant 설정기 as 설정기 프로세스
    사용자->>지그: zig build 실행
    지그->>메이커: 빌드 시스템과 패키지 관리 시작
    메이커->>설정기: build.zig 설정 계산 요청
    설정기-->>메이커: 직렬화된 빌드 설정 전달
    메이커->>메이커: 패키지 처리와 빌드 그래프 실행
    메이커-->>사용자: 빌드 결과 반환
```

- `zig build --watch` 같은 장기 실행 흐름에서 이 구조가 중요해짐
  - 파일 변경을 감시하다가 build.zig나 관찰된 설정 파일이 바뀌면 configurer만 다시 돌리면 됨
  - build server 입장에서는 서버가 죽고 클라이언트가 다시 연결하는 꼴을 피할 수 있음
  - 대신 클라이언트에게 "설정이 바뀌었다"고 알려주는 흐름으로 갈 수 있음

- 대부분은 non-breaking이지만 관찰 가능한 차이는 있음
  - `--maker-opt` 플래그는 `ZIG_DEBUG_MAKER` 환경변수로 대체됨
  - `--zig-lib-dir` 플래그는 `ZIG_LIB_DIR` 환경변수로 대체됨
  - 개발자가 빌드 스크립트나 도구에서 이 플래그를 직접 쓰고 있었다면 체크해야 함

> [!IMPORTANT]
> Zig 0.17.0의 주요 블로커는 build server protocol MVP, build script path dependency 개념, `zig build --watch`의 build script 변경 감지, cwd 차이로 인한 build script cache miss 문제임

- 같은 개발 로그에는 Zig 0.17.0 주변의 큰 변화도 같이 보임
  - SPIR-V 백엔드는 `@SpirvType`, mesh/task shading 호출 규약, 멀티스레드 codegen, `.spv` object linking까지 진전됨
  - `@bitCast`는 메모리 바이트 재해석이 아니라 논리적 bit layout 기준으로 재정의됐고, 이 변경으로 Zig 컴파일러 자체도 약 5% 성능 개선을 봤다고 함
  - 새 ELF linker는 x86_64 Linux에서 외부 라이브러리와 C 소스를 포함한 incremental rebuild를 수백 ms 수준으로 보여줌

---

## 기술 맥락

- 이번 변경의 핵심 선택은 패키지 관리 로직을 컴파일러 바이너리에 묶어두지 않고 maker 프로세스 쪽으로 옮긴 거예요. Zig는 컴파일러가 빌드 시스템과 패키지 관리자까지 품고 있어서 편하지만, 그만큼 내부 경계가 흐려지면 도구 연동이 어려워지거든요.

- 왜 maker가 부모가 되어야 하냐면, watch 모드와 build server는 오래 살아 있는 프로세스를 원하기 때문이에요. build.zig 설정이 바뀔 때마다 서버가 죽고 클라이언트가 재접속하면 ZLS 같은 도구 입장에서는 상태 관리가 지저분해져요.

- 대안은 기존처럼 컴파일러가 패키지 관리를 계속 담당하는 방식인데, 그러면 HTTP, TLS, Git, 압축 처리 같은 꽤 큰 기능 덩어리가 계속 컴파일러 실행 파일에 들어가요. 이번 변경은 그 코드를 소스 형태로 배포해서 수정 가능성을 높이고, 컴파일러 본체 크기도 줄이는 쪽을 택한 거예요.

- 실무 사용자에게 바로 보이는 건 플래그 변경 정도지만, 영향 범위는 빌드 캐시, 패키지 fetch, 언어 서버, watch 모드까지 이어져요. Zig가 0.17.0으로 가면서 개발 경험을 빠르게 만들려고 내부 아키텍처를 계속 갈아엎는 중이라고 보면 돼요.

## 핵심 포인트

- zig build, zig fetch, zig init, zig libc 관련 로직이 maker 프로세스로 이동했다
- 컴파일러 바이너리는 14.1MiB에서 13.5MiB로 약 4% 줄었다
- 네트워킹 패키지 관리 작업은 ReleaseSafe 모드와 호스트 CPU crypto 명령을 활용할 수 있게 됐다
- Zig 0.17.0 전까지 build server protocol MVP와 watch 모드 개선 등이 주요 블로커로 남았다

## 인사이트

이건 단순한 리팩터링이 아니라 Zig가 컴파일러, 빌드 시스템, 패키지 관리자, 언어 서버 사이 경계를 다시 긋는 작업이다. 작은 언어 생태계일수록 이런 내부 구조 변경이 개발자 경험 전체를 크게 바꾼다.
