본문으로 건너뛰기

© 2026 Molayo

GeekNews헤드라인2026. 06. 15. 03:46

Nix Flakes와 그에 대응하는 Guix 기능들

요약

본 글은 Nix Flakes와 Guix 환경의 기능을 비교 분석합니다. Flakes는 프로젝트 의존성 관리 및 개발 환경을 단일 스키마로 통합하여 표준화된 접근 방식을 제공하는 반면, Guix는 직교적이고 작은 도구들의 조합으로 유사한 재현 가능한 환경을 구축함을 설명합니다.

핵심 포인트

  • Flakes: 단일 진입점과 표준 스키마를 통해 의존성 관리를 용이하게 함.
  • Guix: 작고 독립적인 도구들의 조합으로 유연하고 직교적인 시스템을 구성함.
  • Nix와 Guix는 구조적 차이가 있으나, 재현 가능한 환경 구축이라는 목표는 공유함.
  • Flakes의 표준화된 출력 스키마가 장점이지만, 경직성(rigid)이 단점으로 지적됨.

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와 특별한 self input을 받아 packages, dev shells, NixOS configurations, overlays 등을 담은 structured attrset을 반환하는 함수임

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가 사용됨

Guix의 first-class data types

Guix에는 Flakes처럼 단일 output schema가 없고, 여러 command가 소비할 수 있는 first-class data types가 있음

Guix project는 package definitions가 있는 channel, development용 manifest.scm, deployment용 system.scm, operating-system 또는 home-environment declaration 등을 조합해 제공할 수 있음

Guix에서는 이런 파일들이 special entry point file을 요구하지 않으며, Scheme values를 정의하는 Scheme files일 뿐임

Guix에서는 관련 guix subcommand에 파일을 지정하면 command가 처리하며, 별도 ceremony나 schema validation이 필요 없음

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하게 둠

개발 환경

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임

이 사이트는 모바일에서 읽기가 너무 답답함: 글자가 약간 작고, 스크롤할 때마다 계속 방해함
첫 번째 비교 이후로는 읽을 수가 없었는데, 계속 목차로 튕겨 올라가기 때문임

아예 읽을 수가 없음. 요요처럼 움직임. 최근에 정말 읽고 싶었던 글 중 하나였는데, 역대급으로 좌절스러운 읽기 경험이라 실망스러움

데스크톱에서도 같은 일이 생김. 말도 안 되고, 의도적으로 접근성을 망친 것처럼 보임

글을 읽고도 프로젝트의 의존성을 어떻게 지정하고 고정해야 하는지 아직 잘 모르겠음. 배포하고 공유하려면 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 체크아웃이 필요해서 처음 구축 비용이 매우 큼. 한 번 만든 뒤 색인을 유지하는 비용은 낮을 것임

사이트 문제와 이 스레드를 coopi에게 알려뒀으니 곧 고쳐지길 바람
완전히 Guix 쪽으로 기운 입장에서, coopi가 말한 것처럼 Guix에도 Nix처럼 flake.nix 하나나 nix 디렉터리 하나로 모든 것을 담는 표준 파일/디렉터리가 있으면 좋겠음. 다만 Scheme 모듈을 가져오려면 올바른 경로를 지정해야 해서 불가능할 수도 있음
이 Lobsters 글에는 저자가 말하는 것들이 들어 있으니 태그는 nix와 lisp만으로도 충분해 보임

linux를 빼자는 건 설득되지 않음. 둘이 공통으로 가진 유일한 커널이니까 :P 다만 말한 대로 unix는 어울리지 않을 가능성이 큼

flakes처럼 채널이 무엇을 제공하는지 자동으로 추론하는 데 도움을 주는 구조화된 채널 자료형도 있으면 좋겠음
예를 들면 이런 식임:

그리고 새 채널을 만들고 다루는 데 도움을 주는 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배 정도 느려지는 것, 예를 들어 510초가 1530초가 되는 정도라면 받아들일 수 있지만, 내가 시도했을 때는 그 정도와는 거리가 멀었음

AI 자동 생성 콘텐츠

본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0