콘텐츠로 이동

pix

읽기 쉬운 Python으로 Nix 내부 구조를 탐구합니다.

Nix의 핵심 알고리즘 — 스토어 경로 해싱, NAR 직렬화, derivation 파싱, 데몬 와이어 프로토콜 — 은 수십 개의 C++ 소스 파일에 걸쳐 묻혀 있습니다. pix는 각각을 간결한 Python으로 재구현하여 로직을 직접 읽고, 수정하고, 한 줄씩 따라갈 수 있게 합니다.

모든 모듈은 실제 nix CLI와 동일한 출력을 생성하며, 테스트 스위트로 검증됩니다. 코드 자체가 문서이고, 이 페이지들은 그에 대한 해설입니다.

Nix 내부에는 무엇이 있는가

nix build를 실행하면 내부적으로 많은 일이 일어납니다. pix는 이를 한 번에 하나씩 이해할 수 있는 조각으로 나눕니다:

개념 Nix가 하는 일 pix 모듈 문서
Base32 스토어 경로 해시를 위한 커스텀 인코딩 — RFC 4648이 아님 base32.py 차이점
해시 압축 SHA-256 (32 B)을 160비트 (20 B)로 XOR-폴드 hash.py 스토어 경로 계산에서
NAR 결정론적 아카이브 형식 — 타임스탬프 없음, uid 없음, 오직 콘텐츠만 nar.py 와이어 형식 명세
스토어 경로 핑거프린트 문자열로부터 /nix/store/<hash>-<name> 계산 store_path.py 전체 알고리즘
Derivation ATerm 형식의 .drv 파일; hashDerivationModulo로 순환 의존성 해결 derivation.py 형식 + 해싱
데몬 프로토콜 uint64-LE 프레이밍, stderr 로그 스트림, 오퍼레이션 옵코드를 사용하는 Unix 소켓 daemon.py 프로토콜 명세

pixpkgs — pix 위에 쌓기

내부 구조를 이해했다면, pixpkgs는 그 위에 nixpkgs 스타일의 패키지 세트를 구축하는 방법을 보여줍니다. Nix 패턴을 Python 관용구로 매핑합니다:

Nix 패턴 Python 관용구 pixpkgs 모듈
mkDerivation drv() 함수 → Package 데이터클래스 drv.py
callPackage inspect.signature + getattr package_set.py
문자열 보간 (${pkg}) 출력 경로를 반환하는 __str__ drv.py
pkg.override 병합된 kwargs로 drv() 재호출 drv.py
nix-store --realize realize() → 데몬 add_text_to_store + build_paths realize.py

자세한 내용은 pixpkgs API 레퍼런스를 참고하세요.

오버레이와 부트스트랩

Nix에서 가장 깊은 토끼굴: GCC를 빌드하려면 GCC가 필요한데, nixpkgs는 이를 어떻게 해결하나? 답은 고정점(fixed-point)으로 합성되는 오버레이 — 그리고 이것은 Python의 self와 메서드 오버라이드에 놀랍도록 잘 대응됩니다. 네 가지 Python 구현을 탐구하며, 각각 다른 실패 모드를 드러냅니다:

실험 패턴 final prev
A 클래스 상속 self (MRO) self._prev (수동)
B __getattr__ 체인 _final 참조 _prev 링크
C 지연 고정점 LazyAttrSet 프록시 prev 딕셔너리
D 클래스 데코레이터 self (MRO) self._prev (자동)

클래스 상속에서의 무한 재귀 함정, 실제 nixpkgs 7단계 부트스트랩, 그리고 트레이드오프 비교를 포함한 전체 분석은 오버레이와 부트스트랩에서 확인하세요.

읽는 순서

모듈들은 서로 의존합니다. 아래에서부터 시작하세요:

pix (Nix 내부 구조):
  1. base32.py        ← 가장 단순: 인코딩만
  2. hash.py          ← 함수 하나: XOR-폴드
  3. nar.py           ← 직렬화 형식, hash 사용
  4. store_path.py    ← 핵심 알고리즘, base32 + hash 사용
  5. derivation.py    ← 파싱 + hashDerivationModulo 트릭
  6. daemon.py        ← 독립적: Unix 소켓 와이어 프로토콜

pixpkgs (패키지 세트 레이어, pix 사용):
  7. drv.py           ← drv() + Package: mkDerivation 등가물
  8. package_set.py   ← PackageSet.call(): callPackage 등가물
  9. realize.py       ← .drv를 스토어에 쓰고 데몬으로 빌드

각 pix 파일은 자체적으로 완결되며 150줄 미만입니다. 전체 코드베이스를 한 번에 읽을 수 있습니다.

직접 해보기

nix develop

# pix가 nix와 정확히 같은 해시를 계산하는지 확인
python -m pix hash-path ./pix/base32.py --base32
nix hash path ./pix/base32.py --type sha256 --base32
# 같은 출력

# 스토어 경로 계산 후 데몬을 통해 검증
python -m pix store-path ./pix --name pix-source
python -m pix add-text hello.txt "hello world"
python -m pix drv-show /nix/store/...-hello.drv

검증

pytest tests/ pixpkgs/tests/ -v   # 41개 테스트, 모두 실제 nix와 비교

이 문서 사용법

  • 내부 구조 — 여기서 시작하세요. 다이어그램, 헥스 덤프, 프로토콜 트레이스와 함께 Nix가 어떻게 동작하는지 설명합니다.
  • API 레퍼런스 — 각 모듈의 함수 시그니처와 사용 예제.
  • CLI 레퍼런스 — 빠른 실험을 위한 python -m pix 명령어.