Nix Flakes와 그에 대응하는 Guix 기능들
(coopi.neocities.org)- Nix Flakes는 프로젝트 의존성, 잠금, 출력 스키마, 개발 환경을
flake.nix와flake.lock중심으로 묶고, Guix는 channels, manifests,guix describe,guix shell,operating-system같은 직교 도구 조합으로 같은 종류의 기능을 제공함 - Flakes는 프로젝트별
inputs와 자동flake.lock으로 의존성을 고정하고, Guix는 사용자별guix describe와 프로젝트에 커밋을 적은channels.scm,guix time-machine으로 재현 가능한 환경을 구성함 - 순수성은 Flakes에서 restricted evaluation으로 강제되고, Guix에서는 Scheme 모듈 구조와 명시적 입력, 격리된 빌드 컨테이너를 통해 설계상 달성됨
- 출력 구조는 Flakes가
packages,devShells,nixosConfigurations같은 표준 attrset을 제공하는 반면, Guix는<package>, manifest,operating-system, service 같은 투명한 Scheme 레코드와 파일을 각 명령이 직접 소비함 - 선택 기준은 단일 진입점과 표준 스키마를 선호하면 Flakes가 맞고, 작고 독립적인 도구를 조합하는 방식을 선호하면 Guix가 더 잘 맞음
핵심 비교
- Nix flake에 해당하는 단일 Guix 기능은 없으며, Nix Flakes가 여러 문제를 하나의 큰 기능으로 해결하는 반면 Guix는 더 작고 직교적인 도구들의 조합으로 대응함
- Guix는 Nix daemon을 재사용했으며, build isolation과 store management를 담당하는 C++ 구성요소를 공유함
- Guix는 Nix daemon 위의 언어, 패키지 정의, 서비스 시스템 등 대부분을 Guile Scheme으로 새로 구현함
- Guix와 Nix는 derivation format인 ATerm과 daemon 계보를 공유하지만, daemon 위의 구조는 Guix 자체 방식으로 구성됨
- Guix는 Flakes가 제공하는 capabilities를 갖고 있지만, 이를 다른 형태로 제공함
Nix Flake의 기본 구조
- Nix flake는 root에
flake.nix파일을 가진 source tree이며, 보통 Git repository 형태임 flake.nix의 존재가 source tree를 flake로 만들며, 파일은description,inputs,outputs같은 구조를 가짐description은 사람이 읽을 수 있는 문자열로 flake가 제공하는 내용을 나타냄inputs는 다른 flakes, Git repos, tarballs 같은 dependencies를 선언하며, Nix가 이를 fetch하고 evaluate한 뒤outputs함수에 전달함outputs는 resolved inputs와 특별한selfinput을 받아 packages, dev shells, NixOS configurations, overlays 등을 담은 structured attrset을 반환하는 함수임-
예시 구조와 실행 대상
- 예시
inputs의nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";는 GitHub의NixOS/nixpkgs저장소에서nixos-unstablebranch를 가져온다는 의미임 - 예시 flake는
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" ];와nixpkgs.lib.genAttrs를 사용해 여러 CPU architecture별 outputs를 생성함 - Flakes는
packages.<system>수준을 요구하며, 예시에서는packages아래defaultpackage를pkgs.buildGoModule로 정의함 src = ./.;는 전체 Git repository를 source로 사용함devShells는nix develop이 참조하는 개발 shell 정의이며, 예시에서는pkgs.mkShell과buildInputs = with pkgs; [ go gopls gotools ];를 사용함
- 예시
-
flake.lock과 순수 평가- Nix 명령을 flake에 대해 실행하면 Nix는 모든 input과 transitive input을 정확한 revision으로 고정하는 JSON 파일
flake.lock을 생성함 flake.lock은 machine과 시간에 걸쳐 build reproducibility를 가능하게 하는 lock file임- Flakes는 pure evaluation을 강제하며,
$NIX_PATH,builtins.currentSystem, environment variables가 암묵적으로 들어오지 못하고 모든 것이 explicit해야 함 - Flakes가 수행하는 기능은 dependencies 선언, dependencies pinning, purity 강제, standard output schema 제공, reproducible sharing, development environments 정의로 정리됨
- Nix 명령을 flake에 대해 실행하면 Nix는 모든 input과 transitive input을 정확한 revision으로 고정하는 JSON 파일
Guix의 대응 방식
- Guix는 Nix 2.4에서 Flakes가 2021년 11월 1일 도입되기 전에 Flakes 기능 상당수에 대한 해법을 이미 갖고 있었음
- Guix channels mechanism은 2018~2019년경 도입됨
- Guix의 해법은 orthogonal하며, 단일 monolithic abstraction을 채택하지 않고 각 도구를 독립적으로 사용할 수 있음
-
Channels와 의존성 선언
- Flake에서는
flake.nix안에 dependencies를 직접 선언하며, 예시에서nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";와home-manager.url = "github:nix-community/home-manager";를 사용함 - Flake input의
inputs.nixpkgs.follows = "nixpkgs";는home-manager자체의nixpkgsinput을 가져오지 않고 현재 flake의nixpkgs를 사용하게 해 서로 다른 nixpkgs copy 두 개가 생기는 상황을 피함 - Guix의 channels는 Guile modules를 포함하는 Git repository이며, 보통 package definitions를 담지만 services, system configurations, 임의 Scheme code도 포함할 수 있음
- Guix channels는
~/.config/guix/channels.scm에 선언하며, 이 Scheme 파일은 channel records의 list를 반환함 guix pull은 모든 channels를 fetch하고 compile하며, 해당 modules를 모든guixcommand에서 사용할 수 있게 함- Channels는 repository root의
.guix-channel파일을 사용해 다른 channels에 대한 dependencies를 선언할 수 있음 - Guix channels의 channel dependency는 flake의
inputs와 대략 유사하며,guix pull실행 시 transitive channel dependencies가 함께 fetch됨
- Flake에서는
-
프로젝트별 의존성과 사용자별 의존성
- Flakes는 per-project 방식으로 각 repository가 자체
flake.nix와 inputs를 가지며, channels는 system-wide 또는 per-user 방식으로channels.scm이 모든guixinvocations에 적용됨 - Flakes는 서로 다른 프로젝트가 서로 다른 dependency set을 자연스럽게 갖도록 지원하며, Guix에서는 같은 효과를 위해 보통
guix time-machine또는 separate profiles를 사용함 - Flakes는
github:NixOS/nixpkgs,git+https://...같은 URL-like syntax를 사용하며, channels는 plain Git URLs를 사용함 - Flake syntax는 quick references에 더 ergonomic하고, channels는 더 단순하고 explicit함
- Flakes는
flake = false;로flake.nix가 없는 repositories를 non-flake inputs로 지원함 - Guix에서 channel은 Scheme files가 들어 있는 Git repository이므로 특별한 opt-in이 필요 없으며, Guile modules가 있는 어떤 repository도 channel이 될 수 있음
- Flakes는 per-project 방식으로 각 repository가 자체
고정, 재현성, 시간 이동
-
flake.lockflake.lock은 JSON graph이며, 모든 input은 정확한 commit hash로 pinning되고 Nix는 fetch한 source tree 전체의 hash인narHash를 검증함flake.lock은 repository에 commit되므로, clone한 사람은 동일한 dependency versions를 받음flake.lock의original은 요청한 대상이고locked는 실제로 얻은 대상임flake.lock의 two-layer system은nix flake lock --update-input nixpkgs처럼 특정 input만 업데이트하고 나머지는 유지하는 selective update를 가능하게 함
-
guix describe와guix time-machine- Guix는
guix pull실행 시 모든 channels의 정확한 commits를 기록하며,guix describe가 이 정보를 보여줌 guix describe출력은 generation 번호, 날짜, current 표시, channel 이름, repository URL, branch, commit을 포함함- Guix의 recorded channel commits는 lock file에 해당하지만, project directory의 파일이 아니라
~/.config/guix/current에 Guile profile로 존재함 - 재현 가능한 환경을 공유하려면 Guix에서
guix time-machine을 사용할 수 있음 guix time-machine --commit=8a1ab328 -- shell -m manifest.scm은 Guix 자체를 특정 revision으로 pinning한 뒤 그 revision의 package definitions를 사용해guix shell을 실행함guix time-machine은 필요한 경우 해당 revision을 download하고 compile하며, package definitions가 정확히 해당 commit 상태인 isolated environment를 생성함- 프로젝트 repository에 pinned commits를 가진
channels.scm을 check in하는 Guix 패턴도 있음 guix time-machine -C channels.scm -- shell -m manifest.scm은 repository에 포함된channels.scm을 사용해 exact environment를 재현함
- Guix는
-
두 방식의 차이
flake.lock은 per-project이면서 automatic이고,guix describe는 per-user이면서 automatic임- Pinned commits가 들어간
channels.scm은 Guix에서 per-project pinning을 제공하지만 manual 방식임 - Guix는 per-project pinning ergonomics를 개선 중이지만, 현재 workflow는 더 explicit setup이 필요함
flake.lock은 machine-readable JSON graph이고, Guix의 대응물은 commit hashes를 가진 channels를 나열한 Scheme file임- 두 방식 모두 dependency pinning 목표를 달성하지만, flake lock은 모든 transitive input에
original과lockedentries를 가진 full dependency graph라 더 structured함 guix time-machine은 direct flake equivalent가 없는 기능이며, pinned dependency versions뿐 아니라 package collection의 완전히 다른 historical state로 이동할 수 있음
순수성 모델
- Flakes는 restricted evaluation context에서 실행되며,
builtins.currentSystem,builtins.getEnv,$NIX_PATH사용이 금지되거나 무시됨 - Flakes에서 모든 것은 declared inputs에서 와야 하며, implicit state에 accidental dependency가 생기기 어렵게 함
- Flakes의 pure evaluation trade-off는 system detection을 위해 명시적
systemparameters가 곳곳에 필요하고, environment variables 읽기가 불가능하다는 점임 - Flakes에서 impure escape hatch가 필요할 때는
--impure를 명시적으로 전달해야 함 - Guix는 별도 pure evaluation mode가 필요 없으며, evaluation이 convention상 이미 pure함
- Guile modules는 environment variables에 명시적으로 전달하지 않는 한 접근하지 않음
- Guix에는
$NIX_PATH에 해당하는 것이 없으며, packages를 search path가 아니라 module system을 통해 resolve함 - Guix에는
builtins.currentSystem에 해당하는 개념이 없고, systems는 package metadata와--systemflag로 명시함 - Guix의 build도 pure하며, builds는 explicitly declared inputs만 보이는 isolated containers에서 실행됨
- Guix builds에서는
/usr/bin,/etc, network access가 없으며, network access 예외는 fixed-output derivations에 한정됨 - Build sandboxing 방식은 Nix와 Guix가 본질적으로 같은 접근을 공유함
- Guix는 Scheme modules 구조를 통해 architecture 차원에서 purity를 달성하고, Flakes는 원래 impure한 system 위에 restricted evaluation mode를 얹어 purity를 강제함
출력 스키마와 데이터 모델
-
Flake output schema
- Flakes는 outputs에 대한 standard schema를 정의하며,
packages.<system>.<name>은nix build,devShells.<system>.<name>은nix develop,apps.<system>.<name>은nix run에서 사용됨 - Flake output schema에는
nixosConfigurations.<name>,overlays.<name>,nixosModules.<name>,formatter.<system>,templates.<name>,checks.<system>.<name>도 있음 - Flake output schema의 standardization은
nix build .,nix run,nix flake show가 일관된 위치를 참조하게 해 discoverability를 높임 - Flake output schema의 단점은 rigid하다는 점이며, 임의 output types를 추가하려면 Nix 자체 수정이 필요하지만 작은 extension mechanism은 존재함
- Flake의
<system>parameter 때문에 multi-platform support를 explicit하게 처리해야 하며,forAllSystems,flake-utils,flake-parts같은 helper functions 또는 libraries가 사용됨
- Flakes는 outputs에 대한 standard schema를 정의하며,
-
Guix의 first-class data types
- Guix에는 Flakes처럼 단일 output schema가 없고, 여러 command가 소비할 수 있는 first-class data types가 있음
- Guix에서 packages는
<package>records로 정의되고guix install,guix build가 사용함 - Guix에서 manifests는 Scheme files로 정의되고
guix shell -m,guix package가 사용함 - Guix에서 system configs는
operating-system으로 정의되고guix system reconfigure가 사용함 - Guix에서 home configs는
home-environment로 정의되고guix home reconfigure가 사용함 - Guix에서 services는
<service>records로 정의되고operating-system의servicesfield가 사용함 - Guix에서 channels는 Git repos이며
guix pull이 사용함 - Guix에서 package variants는 Scheme procedures이며
--with-input,--transform이 사용함
-
파일과 패키지 정의
- Guix project는 package definitions가 있는 channel, development용
manifest.scm, deployment용system.scm,operating-system또는home-environmentdeclaration 등을 조합해 제공할 수 있음 - Guix에서는 이런 파일들이 special entry point file을 요구하지 않으며, Scheme values를 정의하는 Scheme files일 뿐임
- Guix에서는 관련
guixsubcommand에 파일을 지정하면 command가 처리하며, 별도 ceremony나 schema validation이 필요 없음 - 예시
manifest.scm은specifications->manifest에"guile","guile-git","guile-json"package names list를 넘겨 development environment를 선언함 - 예시
mylib.scm은 Guix의 Nix derivation 대응물인<package>record를 정의하며, package fields를 programmatically query할 수 있음 - 예시 package definition은
(name "mylib"),(version "0.1.0"),(source (local-file ".")),(build-system gnu-build-system),(inputs (list guile guile-git)),(home-page "https://example.com"),(license gpl3+)를 가짐 - Guix의
local-file은 build time에 current directory의 files를 가져오며, Nix의src = ./.;와 유사함 - Guix의
gnu-build-system은./configure && make && make install방식이며, Guix에는cmake-build-system,python-build-system등 다른 build systems도 있음 - Guix는 Nix에서
stdenv가gcc와coreutils를 implicit하게 제공하는 것과 달리 dependencies를 모두 explicit하게 둠
- Guix project는 package definitions가 있는 channel, development용
개발 환경
- Flakes의
devShells예시에서는devShells.x86_64-linux.default = pkgs.mkShell { buildInputs = with pkgs; [ go gopls gotools ]; shellHook = '' echo "Welcome to the devShell!" ''; };를 사용함 mkShell은 build될 때 shell environment를 만드는 derivation을 생성하며,buildInputs는 shell 안의PATH에 들어가고shellHook은 shell 진입 시 arbitrary bash를 실행함- Flake dev shell에는
nix develop또는 named shell용nix develop .#my-shell로 진입함 - Guix development environment는
manifest.scm에서specifications->manifest에 package specification strings list를 넘겨 정의할 수 있음 - 예시 Guix manifest는
"go","gopls","go-tools"를 선언함 - Guix manifest 기반 shell에는
guix shell -m manifest.scm으로 진입함 - Guix는 ad-hoc environment에서 파일 없이
guix shell go gopls go-tools처럼 command line package names만 전달할 수 있음 guix shell은 full isolation을 위한--container, standard Linux filesystem layout을 기대하는 프로그램 실행용--emulate-fhs, Guix container 안에서 Guix를 실행하는--nesting을 지원함- Guix manifests는 더 큰
flake.nix구조에 embedded되지 않은 standalone Scheme files임 guix shell은 파일 없이도 동작할 수 있지만,nix develop은 flake 또는 legacy interface의shell.nix가 필요함- Flakes는
devShells.x86_64-linux.test,devShells.x86_64-linux.default같은 named dev shells를 제공함 - Guix manifests는 named dev shells 대신
manifest.scm,test-manifest.scm같은 별도 파일을 나란히 두는 방식임 - Nix Flakes와 Guix 모두 containerized development를 지원함
시스템 구성
-
NixOS와 Flakes
- Flakes의
nixosConfigurations예시에서는nixpkgs.lib.nixosSystem이 NixOS modules list를 받아 kernel, services, config files 등을 포함한 full system derivation을 생성함 - Flake 기반 NixOS 배포 예시 명령은
nixos-rebuild switch --flake .#myhost임 - 예시
nixosConfigurations.myhost는system = "x86_64-linux";와modules = [ ./configuration.nix home-manager.nixosModules.home-manager ];를 포함함 - NixOS modules는
options,config,mkIf,mkDefault,mkForce를 통한 priority-based merging을 사용하는 module system임 - NixOS 모듈 시스템은 여러 모듈이 같은 옵션을 설정해도 시스템이 우선순위를 해소하며, 수십 개 모듈이 같은 구성에 기여해도 충돌을 피하기 쉬움
- Flakes의
-
Guix
operating-system- Guix의
operating-system은 function이 아니라 Scheme record이며, 각 field는 named typed value로 Guix가 validate함 - Guix system 배포 예시 명령은
guix system reconfigure config.scm임 - 예시
operating-systemrecord는(host-name "myhost"),(timezone "Etc/UTC"), bootloader configuration, file systems, services를 포함함 - Guix bootloader configuration 예시는
grub-efi-bootloader와 target"/boot/efi"를 사용하며, Guix는 GRUB, U-Boot 등을 지원함 - Guix file systems는 list로 선언되며,
%base-file-systems는/dev,/proc,/sys등에 대한 defaults를 제공함 - Guix services는 directed acyclic graph(DAG)를 이루며, 각 service는 다른 services를 extend할 수 있음
%base-services는 Shepherd init system, syslog, networking 등 필수 services를 제공함- Guix system configuration에는 special output type이 필요 없고,
operating-systemrecord를 반환하는 파일을guix system에 지정하면 됨 - Guix의 서비스 조합은 기존 시스템에 임의의 방식으로 연결되는 새 서비스를 작성하기 쉽게 만듦
- Guix의
탐색성과 레지스트리
- Flakes에는 프로젝트 의존성, 출력, 발견 가능한 스키마를 한 파일에서 선언하는 표준 진입점
flake.nix가 있음 - Guix 프로젝트는
manifest.scm,channels.scm,guix.scm,package.scm등 관례 기반 파일을 사용할 수 있음 guix shell이 자동으로 인식하는 프로젝트 파일로guix.scm를 표준화하려는 움직임이 있지만,flake.nix만큼 확립되지는 않았음- Flakes에는 짧은 이름을 URL에 매핑하는 전역 레지스트리 flake-registry가 있으며, 예시는
nix run nixpkgs#hello,nix build github:NixOS/nixpkgs#firefox임 - Guix는 비슷한 편의성을 위해 패키지 명세를 사용하며, 예시는
guix shell hello,guix install firefox임 - Guix에는 임의의 Git 저장소를 짧은 이름으로 가리키는 레지스트리 대응물이 없고 URL을 직접 사용함
- Nix 레지스트리는
nixpkgs가 레지스트리 항목인지, 로컬 경로인지, 다른 대상인지 항상 명확하지 않아 혼란의 원천이 된 적이 있음 nix flake show는 flake가 제공하는 모든 항목을 트리 뷰로 보여주는 명령임- Guix에는 패키지용
guix search와 서비스용guix system search가 있지만, 특정 프로젝트나 저장소가 제공하는 모든 항목을 보여주는 대응 명령은 없으며 Scheme 파일을 직접 확인해야 함 - Flakes는
nix flake show가 project가 제공하는 것들을 consistent view로 보여준다는 점에서 discoverability가 강함 - Guix projects는 더 ad-hoc하며, 어떤 파일을 봐야 하는지 알아야 하고 standard single-entry-point file이 없음
- Guix는 모든 것이 Scheme이기 때문에 schema 없이 원하는 것을 정의하고 조합할 수 있어 flexibility가 강함
패키지 모델과 그래프 재작성
- Nix에서 패키지는
stdenv.mkDerivation { ... }호출로 derivation을 반환하는 함수이며, 그 결과는 불투명한 attribute set임 - Guix에서 패키지는
<package>레코드이며, 이름이 붙은 필드를 가진 투명한 데이터 구조라 표준 Scheme 절차로 검사, 변환, 조합할 수 있음 - Guix package definitions는 opaque functions가 아니라 transparent records이므로 special tooling 없이 inspect와 transform을 programmatically 수행할 수 있음
- Guix에서는 packages가 data이므로 graph rewrites를 쉽게 수행할 수 있음
- Guix에서는
package-input-rewriting으로 전체 의존성 그래프를 순회해perl을perl-minimal로 바꾸는 작업을 표현할 수 있음 - Guix의
inherit키워드는coreutils의 모든 필드를 물려받고 지정한 필드만 덮어쓰는 방식으로 패키지를 재정의함 - Nix에는 비슷한 목적의 overlays가 있지만, 불투명한 함수 인터페이스 때문에 검사와 변환이 더 어려워 사용성이 떨어짐
보안 업데이트, 부트스트랩, 인증
- Guix의 grafting은 모든 의존 패키지를 다시 빌드하지 않고 의존성 트리에 보안 업데이트를 적용할 수 있게 함
- glibc 같은 저수준 라이브러리에 취약점이 있을 때 Guix는 저장소 경로를 다시 작성해 수정 버전으로 교체할 수 있음
- Nix는 보안 업데이트 상황에서 모든 것을 다시 빌드하며, 큰 의존성 트리에서는 빌드 시간이 몇 시간 차이 날 수 있음
- Guix는 소스 기반 부트스트래핑에 강하게 집중하며, 전체 시스템을 작은 신뢰 기반에서 빌드할 수 있음
- Guix의 부트스트랩 체인은 약 500바이트 hex assembler에서 시작해 Scheme으로 작성된
mesC 컴파일러,tcc, 전체 GNU toolchain으로 이어짐 - bootstrappable builds 프로젝트는 전체 소스 부트스트랩 세부 사항을 다룸
- Nix는 Guix보다 더 많은 바이너리 시드에 의존함
- 부트스트랩 체인을 감사할 수 없으면 시스템이 실제로 의도한 소스에서 빌드됐는지 완전히 검증할 수 없으므로, 전체 소스 부트스트래핑은 신뢰와 검증 가능성에 중요함
- Guix channels는 암호학적 인증을 기본 지원함
- Guix channel은 특정 커밋과 그 Ed25519 서명으로 구성된 “introduction”을 지정하며, Guix는 해당 introduction부터 현재 커밋까지 전체 서명 체인을 검증함
- Flakes는 신뢰 모델로 HTTPS와 GitHub 인프라를 사용하며, 이는 Guix의 Ed25519 channel authentication과 다른 보안 모델임
요약 표의 핵심 대응 관계
- 의존성 선언은 Flakes가
flake.nix의inputs, Guix가channels.scm과.guix-channel을 사용함 - 의존성 고정은 Flakes가 자동·프로젝트별
flake.lock을 사용하고, Guix가 사용자별 자동guix describe와 프로젝트별 수동 커밋 지정channels.scm을 사용함 - 순수 평가는 flake mode에서 강제되고, Guix에서는 설계상 내재된 특성임
- 출력 스키마는 Flakes가
outputs의 구조화된 attrset을 쓰고, Guix가 ad-hoc Scheme records를 씀 - 개발 환경은 Flakes가
devShells와nix develop, Guix가manifest.scm와guix shell을 씀 - 시스템 구성은 Flakes가
nixosConfigurations와 모듈 시스템, Guix가operating-system과 서비스 DAG를 씀 - 한 명령 재현성은 Flakes가
nix build github:foo/bar, Guix가guix time-machine -C channels.scm -- build형태임 - 프로젝트별 고정은 Flakes가
flake.lock으로 자동 처리하고, Guix가 커밋이 들어간channels.scm으로 수동 처리함 - 탐색성은 Flakes가
nix flake show, Guix가 Scheme 모듈 검사에 의존함 - 패키지 모델은 Flakes/Nix가 불투명 함수, Guix가 투명 레코드임
- init system은 Nix가 systemd, Guix가 GNU Shepherd를 사용함
- 보안 업데이트는 Nix가 전체 재빌드, Guix가 빠른 grafting을 사용함
- 부트스트랩 신뢰는 Nix가 바이너리 시드, Guix가 전체 소스 부트스트랩에 기반함
- 인증된 업데이트는 Flakes가 HTTPS/GitHub 신뢰, Guix가 Ed25519 channel authentication을 사용함
- FHS 지원은 Nix가
buildFHSUserEnv, Guix가--emulate-fhs를 제공함 - 비 Linux 지원은 Nix가 macOS용 nix-darwin, Guix가 GNU Hurd로 정리됨
- 자유 소프트웨어 전용 여부는 Nix가 전용이 아니며 구성 가능하고, Guix는 FSDG를 준수함
결론
- Flakes와 Guix는 재현성, 의존성 관리, 시스템 선언이라는 같은 종류의 문제를 서로 다른 아키텍처 철학으로 해결함
- Flakes는 하나의 파일, 하나의 스키마, 하나의 잠금 파일, 하나의 관례 집합을 갖춘 단일 기능에 가까움
- Guix는 배포용 channels, 환경용 manifests, 구성용
operating-system, 재현성용guix time-machine, 기타 구조를 위한 Scheme records 같은 직교 도구들의 조합임 - 하나의 표준 방식, 하나의 진입점 파일, 하나의 출력 스키마, 하나의 잠금 형식을 선호하면 Flakes가 자연스럽게 맞음
- 작고 독립적인 도구를 조합해 각 도구가 한 가지를 잘하게 하는 Unix 철학을 패키지 관리에 적용하는 방식을 선호하면 Guix가 잘 맞음
- 두 생태계는 패키지 관리가 함수형, 선언적, 재현 가능해야 한다는 아이디어를 중심으로 발전했으며, 서로 다른 구현으로 같은 아이디어를 밀어붙이고 있음
댓글과 토론
Lobste.rs 의견들
-
이 사이트는 모바일에서 읽기가 너무 답답함: 글자가 약간 작고, 스크롤할 때마다 계속 방해함
첫 번째 비교 이후로는 읽을 수가 없었는데, 계속 목차로 튕겨 올라가기 때문임- 아예 읽을 수가 없음. 요요처럼 움직임. 최근에 정말 읽고 싶었던 글 중 하나였는데, 역대급으로 좌절스러운 읽기 경험이라 실망스러움
- 데스크톱에서도 같은 일이 생김. 말도 안 되고, 의도적으로 접근성을 망친 것처럼 보임
-
글을 읽고도 프로젝트의 의존성을 어떻게 지정하고 고정해야 하는지 아직 잘 모르겠음. 배포하고 공유하려면
channels.scm에 각 전이 의존성의 커밋 해시를 수동으로 찾아 넣어야 하는 것처럼 보임
time-machine은 Guix 패키지 집합에만 동작하고, 트리 밖 의존성에는 안 되는 듯함
nix run github:nixos/nixpkgs/<commit hash>#<package>처럼 nixpkgs의 과거 시점 코드도 꽤 쉽게 실행 가능함
Guix가 독특한 부분은 패키지 모음 버전과 패키지 관리자 버전을 분리하지 않는다는 점임. 오래된 패키지를 실행하려면 오래된 Guix 릴리스도 함께 실행하게 되는데, 왜 그걸 원해야 하는지 잘 모르겠음
글에서는 flakes가 커밋을 수동으로 찾아 지정해야 한다고 하면서, 바로 뒤에 커밋을 지정해야 하는 Guix 명령을 예로 듦. Nix flake에서도--override-input으로 nixpkgs 버전을 덮어쓸 수 있지만 지저분하고, 그래서 unflake에서 개선하려는 부분 중 하나임- 내가 글쓴이보다 Guix 사용 경험은 적지만 문서는 어느 정도 봤으니 몇 가지 답해보겠음
보통 전용guix shell환경에서 개발하다가, 공유할 단계가 되면guix describe -f channels > channels.scm로 모든 커밋 해시를channels.scm에 기록하는 흐름임
declaring channel dependencies 문서를 보면 의존성 커밋은 지정할 수 있지만, 그 의존성이 다시 의존성을 가질 때 그쪽도 특정 커밋에 고정됐는지 검증하는 옵션은 없어 보임
time-machine의--commit=표기는 Guix 채널에 해당하지만,-C로 파일에서 채널을 추가로 불러올 수 있음
패키지 관리자와 패키지 레코드에 호환성 깨지는 변경이 생겨도, 이력과 재현성을 잃지 않게 해주는 장점이 있음 - 이를 위해 nixpkgs의 역색인을 만들면 가능함: nixpkgs의 커밋 X부터 Y까지가 특정 패키지의 버전 A를 포함한다는 식임
다만 각 커밋마다 nixpkgs 체크아웃이 필요해서 처음 구축 비용이 매우 큼. 한 번 만든 뒤 색인을 유지하는 비용은 낮을 것임
- 내가 글쓴이보다 Guix 사용 경험은 적지만 문서는 어느 정도 봤으니 몇 가지 답해보겠음
-
사이트 문제와 이 스레드를 coopi에게 알려뒀으니 곧 고쳐지길 바람
완전히 Guix 쪽으로 기운 입장에서, coopi가 말한 것처럼 Guix에도 Nix처럼flake.nix하나나nix디렉터리 하나로 모든 것을 담는 표준 파일/디렉터리가 있으면 좋겠음. 다만 Scheme 모듈을 가져오려면 올바른 경로를 지정해야 해서 불가능할 수도 있음
이 Lobsters 글에는 저자가 말하는 것들이 들어 있으니 태그는nix와lisp만으로도 충분해 보임linux를 빼자는 건 설득되지 않음. 둘이 공통으로 가진 유일한 커널이니까 :P 다만 말한 대로unix는 어울리지 않을 가능성이 큼- flakes처럼 채널이 무엇을 제공하는지 자동으로 추론하는 데 도움을 주는 구조화된 채널 자료형도 있으면 좋겠음
예를 들면 이런 식임:
그리고 새 채널을 만들고 다루는 데 도움을 주는(channel (operating-systems (list my-vm)) (services (list my-system-service)))guix channel명령도 있으면 좋겠음
-
Guix에도 Nix flake의
.inputs.nixpkgs.follows처럼 전이 의존성의 고정값을 덮어쓰는 기능이 있는지 궁금함
또 저자의 Guix 설명 상당 부분이 flakes 이전의 Nix를 떠올리게 함: 표준 진입점이 없고 채널을 쓰는 구조 등. 다만 Guix에서는 형식 체계와 진짜 언어가 있어서 같은 패턴이 고통점이 덜 되는 것 같음. Nix가 더 낫거나 다른 언어였다면 나왔을 대체역사처럼 느껴짐- 그 기능은 무엇에 쓰는 건가?
-
다른 댓글에서 지적한 사용성 문제 때문에 추천하기가 망설여짐. 기본으로 JavaScript를 끄는 NoScript를 써서 나는 알아차리지 못했음
그래도 이 글은 딱 필요한 시점에 왔음. 회사에서 Nix를 많이 쓰는 방향으로 가고 있고 flakes 때문에 조금 고생 중인데, 이 글의 설명이 이전에 읽은 것들보다 훨씬 명확했음- Coopi가 말하길, JavaScript나 CSS가 없어도 읽을 수 있게 점진적 향상을 따르려고 노력했고, JavaScript 쪽은 망쳤지만 적어도 그 철학은 동작하고 있었다고 함. 이제 JavaScript도 고쳐졌을 것이라고 함
-
Coopi의 답변임: 오늘 아침 변경을 했지만 일 때문에 테스트를 못 했고, 알고 보니 JavaScript에 문제가 있었다고 함
-
이 사이트는 iOS 모바일에서 사용할 수 없음. 페이지가 아래쪽에서 로드된 뒤 즉시 위로 스크롤되는 것 같고, 내가 한 화면 이상 아래로 내리면 무언가가 트리거되어 다시 위로 올려버림
읽기 모드는 동작하지만 강조 표시와 원래 꽤 괜찮은 세부 스타일링이 사라짐 -
flakes가 하는 일을 Guix의 여러 도구로도 할 수 있다고 말하는 건 타당하지만, Nix에도 같은 문제를 해결할 수 있는 작고 직교적인 도구들이 예전부터 있었고 지금도 있다는 점은 짚어야 함
flakes가 제공하는 건 표준 프로젝트 진입점과 그것이 가능하게 하는 생태계, 예를 들면 레지스트리임. 글에서도 Guix에는 이 부분이 없다고 함
Guix 사용자들은 표준 진입점이 필요 없다고 판단할 수 있고, 많은 Nix 사용자도 그렇게 판단해 왔음
하지만 직교적인 도구 모음으로 flakes를 할 수 있다고 말하는 건, FreeBSD는 jail로 필요한 걸 다 할 수 있으니 OCI 지원이 필요 없다는 주장과 비슷하게 들림. 표준화가 생태계를 가능하게 한다는 부분을 놓침
Guix에 관심이 많고 기여도 조금 했는데,channels.scm과 함께guix time-machine으로 빌드하는 것이 flake 고정값을 바꾸고 Nix 평가를 하는 것보다 왜 그렇게 오래 걸리는지 비교해보고 싶음. 3배 정도 느려지는 것, 예를 들어 5~10초가 15~30초가 되는 정도라면 받아들일 수 있지만, 내가 시도했을 때는 그 정도와는 거리가 멀었음