플레이크#

Author:

Kiara Grouwstra @kiara

플레이크란 무엇입니까?#

플레이크는 Nix 코드를 공유하기 위한 진입점 파일 flake.nix를 제공합니다. 플레이크를 사용하면 같은 버전으로 프로그램을 쉽게 빌드할 수 있습니다.

flake.nix는 표준 구조로 입력과 출력을 선언하는 파일입니다.

참고: 실험적 기능이며 Nix 2.4가 필요합니다.

이 파일은 다음과 같은 형태일 수 있습니다.

 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와 같은 대규모 저장소에서는 더 느려질 수 있습니다.

  • 구현에는 플레이크와 v3 CLI 모두에 여전히 문제가 있습니다.

  • 플레이크가 파일을 인식하려면 파일이 스테이징되어 있어야 합니다.

대안:

의존성 관리#

플레이크의 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를 사용하여 모듈 간에 전파하십시오.

역사#

  • 구상

  • 설계

    • 플레이크 제안은 너무 많은 문제를 한꺼번에, 그것도 잘못된 추상화 계층에서 해결하려 한다는 비판을 받았습니다.

    • 이 설계에는 버전 관리, 조합성, 교차 컴파일, nixpkgs와의 강한 결합 등을 비롯한 여러 문제가 여전히 남아 있습니다.

    • nix CLI를 둘러싼 미해결 설계 문제도 여전히 많습니다.

  • 구현

  • 절차

    • 설계에 대한 우려가 아직 해소되지 않은 상태에서 RFC가 승인되지 않은 채로(실제로는 병합 시점에 철회됨) 구현이 병합되었고, 이로 인해 절차가 적절했는지에 대한 의문이 제기되었습니다.

    • 해당 RFC는 실험을 마무리할 일정 없이 종료되었습니다.

    • 많은 프로젝트가 플레이크에 의존하게 되면서, 많은 사람의 코드를 깨뜨리지 않고 설계를 반복적으로 개선하기가 더 어려워졌습니다.

  • 커뮤니티

    • 이 설계는 커뮤니티 전체에서 받아들여지지는 않았으며, 예를 들어 Nixpkgs는 내부 도구에서 이를 사용하지 않았습니다. 그 결과 플레이크에 대한 접근 방식이 여러 갈래로 나뉘었습니다. 예를 들어 Determinate Systems사(플레이크와 관련된 독점 기능을 제공하는 회사)는 이 기능을 일방적으로 안정 기능이라고 선언했고, 커뮤니티 주도의 Nix 포크인 Lix는 사실상의 ‘v1’으로 기능 집합을 통합했습니다. 이러한 분화는 애초에 플레이크 실험을 추진하게 한 통합 인터페이스라는 약속을 결국 깨뜨릴 수도 있습니다.

더 읽을거리#