플레이크#
- Author:
Kiara Grouwstra @kiara
플레이크란 무엇입니까?#
플레이크는 Nix 코드를 공유하기 위한 진입점 파일 flake.nix를 제공합니다. 플레이크를 사용하면 같은 버전으로 프로그램을 쉽게 빌드할 수 있습니다.
flake.nix는 표준 구조로 입력과 출력을 선언하는 파일입니다.
이 파일은 다음과 같은 형태일 수 있습니다.
1{
2 description = "My example flake";
3
4 inputs = {
5 nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
6 };
7
8 outputs = { self, nixpkgs }: {
9 packages.x86_64-linux = {
10 default = self.packages.x86_64-linux.hello;
11 hello = nixpkgs.legacyPackages.x86_64-linux.hello;
12 };
13 };
14}
outputs에는 다양한 기본 제공 유형이 포함되지만 확장할 수도 있습니다. 이에 대한 개요는 위키에서 확인할 수 있습니다.
inputs로 의존성을 선언할 수 있습니다.
nix 명령을 실행하면 Nix는 의존성을 고정하기 위해 flake.lock을 생성합니다.
이 의존성에 자체 inputs가 있으면 Nix는 사용할 버전을 찾기 위해 해당 의존성의 lock 파일을 확인합니다. 같은 버전을 사용하면 프로그램이 의도한 대로 동작하는 데 도움이 되지만, 이를 오버라이드할 수도 있습니다.
nix 명령은 기본적으로 플레이크와 네이티브하게 통합됩니다.
nix build github:NixOS/nixpkgs#hello
로컬(예: .) 또는 원격(예: github:NixOS/nixpkgs) 프로젝트 디렉터리에 대한 참조를 전달할 수 있습니다. 자세한 내용은 nix 명령에 대한 참조 문서를 확인하십시오.
플레이크의 별칭은 레지스트리에 저장됩니다. 레지스트리는 명령줄이나 NixOS 옵션 nix.registry로 확장할 수 있습니다.
플레이크 기반 설치에 대한 자세한 설명은 NixOS 매뉴얼에 있습니다.
제 프로젝트에서 플레이크를 사용해야 합니까?#
플레이크는 아직 해결되지 않은 문제가 남아 있는 실험적 확장 형식입니다. 플레이크가 제공하는 기능은 대체로 플레이크 없이도 구현할 수 있습니다.
이미 플레이크를 사용하는 기존 소프트웨어를 실행해야 하거나 플레이크 개발에 기여하고 싶다면 자유롭게 사용하십시오. Nix 코드를 직접 작성하려면 의존성 관리에 관한 가이드도 참고하십시오.[1] 이 개요는 호환성을 유지하면서 플레이크에서 필요한 것(입력 등)을 얻는 데 도움이 됩니다.
발견 가능성#
플레이크를 사용하는 첫 단계는 outputs를 지정하는 flake.nix 파일을 추가하는 것입니다.
장점:
다른 플레이크 프로젝트의 코드를 사용할 수 있습니다.
Nix가
flake.nix의 구조가 유효한지 검사합니다.
단점:
플레이크에는 매개변수가 없습니다. 따라서
flake.nix와 그 최종 사용자는 사용하는system을 명시해야 합니다. 예를 들어flake-utils를 사용하면 이 작업이 더 쉬워집니다.플레이크는 실험적 기능이므로 아직 바뀔 수 있습니다.
대안:
플레이크를 기존 Nix 코드를 감싸는 얇은 래퍼로 사용하십시오. 이렇게 하면 코드를 두 가지 방식 모두로 사용할 수 있습니다.
Nix 모듈을 사용하십시오. 플레이크 사용자는
flake = false;로 이를 가져올 수 있습니다.NixOS 26.05부터는 단일
system.nix진입점에서 하나 이상의 NixOS 설정을 불러올 수 있습니다.
명령 실행하기#
플레이크는 Nix의 v3 nix 명령줄 인터페이스에서 사용합니다. 이 인터페이스는 .이나 github:NixOS/nixpkgs 같은 참조로 프로그램을 빌드하거나 실행할 수 있습니다.
다음을 추가하여 명령 하나에 대해서만 이를 활성화할 수 있습니다:
--experimental-features 'nix-command flakes'
또는 NixOS나 Home Manager 설정에서 다음을 사용하여 영구적으로 활성화할 수 있습니다:
nix.settings.experimental-features = [ "nix-command" "flakes" ];
flake.nix의 packages.x86_64-linux.default에 있는 derivation을 빌드하려면 다음을 실행하십시오:
nix build .#packages.x86_64-linux.default
이를 nix build .#default 또는 그냥 nix build로 줄일 수 있습니다.
nix run은 outputs.apps에 있는 프로그램을 실행합니다. nix run .#default는 outputs.apps.default를 실행합니다. 그냥 nix run만 입력해도 같은 것을 실행합니다.
예를 들어 Nixpkgs의 hello 패키지를 실행하려면 다음과 같이 하십시오:
nix run nixpkgs#hello -- --greeting "hello from flakes"
이는 레지스트리의 별칭 nixpkgs에 설정된 버전을 사용합니다.
Nixpkgs의 nixpkgs-unstable 브랜치에서 hello 패키지를 실행하려면 다음과 같이 하십시오:
nix run github:NixOS/nixpkgs/nixpkgs-unstable#hello
장점:
플레이크는 빌드를 캐시하여 이후의 동일한 빌드에 드는 시간을 절약합니다. 예를 들어 지속적 통합(Continuous Integration)에서 변경되지 않은 빌드를 실행할 때 시간을 절약할 수 있습니다.
플레이크는 원격 저장소에 있는 프로그램까지도 쉽게 실행할 수 있도록 장려합니다.
플레이크는 기본적으로 순수 모드로 실행됩니다. 이는 프로그램을 재현 가능하게 만들 가능성이 더 높은 작성 방식을 장려합니다[2].
Git을 사용하는 프로젝트에서 플레이크는 추적되는 파일만 빌드합니다. 이는 불필요한 재빌드를 막는 데 도움이 됩니다.
단점:
빌드할 때 플레이크 디렉터리 전체를 Nix 스토어로 복사합니다. 이렇게 하면 캐시되지만, Nixpkgs와 같은 대규모 저장소에서는 더 느려질 수 있습니다.
플레이크가 파일을 인식하려면 파일이 스테이징되어 있어야 합니다.
대안:
일반 Nix 파일은 [v2 commands](
nix-build,nix-shell등)와 함께 사용하거나, v3 명령의--file플래그 또는-f와 함께 사용할 수 있습니다.NixOS에서는 NixOS 설정에
nixpkgs.flake.source = pkgs.path;를 지정하여 v3 명령의nixpkgs가 패키지 집합pkgs를 가리키도록 할 수 있습니다. 의존성 관리도 참고하십시오.실험적 기능
fetch-tree의builtins.fetchTree를 사용하면 플레이크가 아닌 진입점에 대해nix run을 에뮬레이션할 수 있습니다[3].
의존성 관리#
플레이크의 inputs 속성으로 의존성을 관리할 수 있습니다. 기본적으로 재귀적 의존성은 암묵적으로 처리됩니다. 하나의 라이브러리가 여러 번 사용되는 경우, 같은 라이브러리의 서로 다른 버전이 사용될 수 있습니다. 원한다면 follows 문을 사용하여 이를 오버라이드할 수 있습니다:
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
};
}
이렇게 하면 Home Manager의 입력이 사용자가 선택한 nixpkgs를 재사용합니다.
장점:
공개된 소프트웨어를 그 소프트웨어가 사용한 버전 그대로 쉽게 재현할 수 있습니다.
재귀적 입력을 오버라이드할 수 있습니다.
단점:
플레이크는 기본적으로 의존성의
flake.lock에 있는 버전을 따르므로,follows로 이를 오버라이드하지 않으면 다음과 같은 문제가 생길 수 있습니다:같은 의존성의 여러 버전.
버전이 활발히 업데이트되지 않는 경우, 오래된 의존성.
의존성을 즉시 가져오므로 사용하지 않을 수도 있는 의존성까지 불러옵니다.
플레이크 입력으로 관리되는 의존성은 플레이크를 함께 사용하지 않으면 오버라이드하기 어렵습니다.
플레이크가 라이브러리로 사용된다면 모든 재귀적 입력에 대해
follows문을 추가해야 합니다. 그렇지 않으면 다운스트림 사용자가 간접 입력에 자신의follows를 추가할 수 없습니다.
대안:
npins로 의존성을 관리하십시오.페처나
builtins.fetchTree같은 함수를 사용하여 의존성을 인라인으로 관리하십시오.inputs.<name>.flake = false;를 사용하십시오.
플레이크 전용 Nix#
플레이크는 (대체로[4]) Nix를 내부 언어로 사용하므로 모든 Nix 코드를 플레이크 파일에 넣을 수도 있습니다. 커뮤니티에서는 이러한 코딩 스타일을 덴드리틱 패턴(dendritic pattern)이라고 부릅니다. 플레이크를 사용하면 flake-parts 라이브러리로 이 패턴을 더 쉽게 적용할 수 있습니다. 이 라이브러리를 사용하면 코드를 플레이크와 비슷한 여러 파일에 나누어 둘 수 있습니다.
장점:
이러한 Nix 코드 어디에서나 플레이크의 스키마와 입력을 사용하기 쉬워집니다.
단점:
플레이크를 사용하지 않고는 이 코드에 접근하기가 더 어려워집니다.
대안:
플레이크를 기존 Nix 코드를 감싸는 얇은 래퍼로 사용하여 코드를 두 가지 방식 모두로 사용할 수 있게 하십시오.
flake-compat라이브러리를 사용하여 플레이크의 기본 패키지나 셸을 플레이크를 사용하지 않는 사용자에게 노출하십시오.필요한 매개변수를 명시적으로 전달하거나 NixOS의
specialArgs를 사용하여 모듈 간에 전파하십시오.
역사#
구상
설계
구현
구현상의 문제도 여전히 남아 있습니다.
절차
설계에 대한 우려가 아직 해소되지 않은 상태에서 RFC가 승인되지 않은 채로(실제로는 병합 시점에 철회됨) 구현이 병합되었고, 이로 인해 절차가 적절했는지에 대한 의문이 제기되었습니다.
해당 RFC는 실험을 마무리할 일정 없이 종료되었습니다.
많은 프로젝트가 플레이크에 의존하게 되면서, 많은 사람의 코드를 깨뜨리지 않고 설계를 반복적으로 개선하기가 더 어려워졌습니다.
커뮤니티
이 설계는 커뮤니티 전체에서 받아들여지지는 않았으며, 예를 들어 Nixpkgs는 내부 도구에서 이를 사용하지 않았습니다. 그 결과 플레이크에 대한 접근 방식이 여러 갈래로 나뉘었습니다. 예를 들어 Determinate Systems사(플레이크와 관련된 독점 기능을 제공하는 회사)는 이 기능을 일방적으로 안정 기능이라고 선언했고, 커뮤니티 주도의 Nix 포크인 Lix는 사실상의 ‘v1’으로 기능 집합을 통합했습니다. 이러한 분화는 애초에 플레이크 실험을 추진하게 한 통합 인터페이스라는 약속을 결국 깨뜨릴 수도 있습니다.
더 읽을거리#
플레이크는 실재하지 않으며 여러분을 해칠 수 없습니다: 플레이크가 아닌 방식으로 Nix 플레이크를 사용하는 가이드 (Jade Lovelace, 2024년 1월)
Nix 플레이크는 한꺼번에 너무 많은 것을 시도한 실험입니다… (댓글) (Samuel Dionne-Riel, 2023년 9월)
실험적이라는 것이 불안정하다는 뜻은 아닙니다 (댓글) (Graham Christensen, 2023년 9월)
The Nix Hour: 플레이크와 기존 Nix 비교 (Silvan Mosberger, 2022년 11월)