This is the complete documentation for Zero to Nix, including the learning journey (start) and concept pages. Learning journey (start) and concept page items begin and end with a --- and all page titles are in bold. # Zero to Nix > Nix와 플레이크를 배우는 안내서 Zero to Nix is a flake-centric resource for learning Nix created by [Determinate Systems](https://determinate.systems/llms.txt). It takes you on a [learning journey](#start-pages) from installing Nix to exploring Nix development environments to building Nix packages and more. It also offers a series of [concept pages](#concept-pages) covering some of the trickier corners of Nix. ## Start pages --- **시스템에서 Nix 실행하기** Published: URL: https://zero-to-nix.com//start/install 이 Zero to Nix 빠른 시작은 한 가지 특정한 독자층을 염두에 두고 작성했습니다. 바로 [Nix]에 대해 들어 본 적은 있지만 아직 잘 알지 못하고 어디서부터 시작해야 할지 확신이 서지 않는 분들입니다. 이 문서는 일상적인 워크플로에서 Nix를 사용하는 방법을 알려 주는 가이드라기보다는, Nix의 기능을 살짝 엿보고 더 나아갈 자신감을 불어넣어 주는 첫 "아하!" 순간들을 경험하도록 돕는 데 목적이 있습니다. 이미 Nix에 익숙하고 업무에서 Nix를 활용하는 방법에 대한 안내를 찾고 계신다면, 이 빠른 시작에서도 얻을 것이 있겠지만 [nix.dev]와 같이 좀 더 실용적이고 가이드 중심인 자료가 더 도움이 될 수 있습니다. **환영합니다**! [Nix]에 관심을 가져 주셔서 정말 기쁩니다. 이 [빠른 시작][start]에서는 시스템에 [Determinate Nix][det-nix]를 설치합니다. 그런 다음 Nix를 사용하여 [개발 환경 만들기][dev]와 [패키지 빌드하기][build] 같은 실용적인 작업을 해 보면서 Nix의 기능을 조금 맛보여 드리겠습니다. [Determinate Nix][det-nix]는 [업스트림 Nix 프로젝트][upstream]를 기반으로 한 [Determinate Systems][detsys]의 다운스트림 배포판입니다. [지연 트리][lazy-trees], [병렬 평가][parallel-eval], [네이티브 Linux 빌더][linux-builder] 등 업스트림 버전에서는 제공하지 않는 다양한 기능을 제공합니다. 시스템에 맞게 설치 과정을 조정해 주는 도구인 [Determinate Nix Installer][nix-installer]를 사용하여 Determinate Nix를 설치하겠습니다. 지원하는 플랫폼은 다음과 같습니다: ## Determinate Nix 설치하기 \{#up} 설치 프로그램이 완료되면 새 터미널 세션을 여십시오. 그러면 `nix` 실행 파일이 `$PATH`에 있을 것입니다. 이를 확인하려면 다음을 실행하십시오: ```shell title="Display the Nix version" nix --version ``` 버전 정보가 출력될 것입니다. :rocket: **성공**입니다! 이제 시스템에 Determinate Nix가 설치되어 바로 사용할 준비가 되었습니다. Zero to Nix에 기여하는 데 관심이 있으시다면 프로젝트 [저장소][repo]의 [매뉴얼][contributing]에서 몇 가지 제안 사항을 확인하십시오. [build]: /start/nix-build [contributing]: https://github.com/DeterminateSystems/zero-to-nix/tree/main/CONTRIBUTING.md [det-nix]: https://docs.determinate.systems/determinate-nix [detsys]: https://determinate.systems [dev]: /start/nix-develop [lazy-trees]: https://docs.determinate.systems/determinate-nix/lazy-trees [linux-builder]: https://docs.determinate.systems/determinate-nix/linux-builder [nix]: https://nixos.org [nix-installer]: /concepts/nix-installer [nix.dev]: https://nix.dev [parallel-eval]: https://docs.determinate.systems/determinate-nix/parallel-eval [repo]: https://github.com/DeterminateSystems/zero-to-nix [start]: /start [upstream]: https://github.com/NixOS/nix --- **Nix로 프로그램 실행하기** Published: URL: https://zero-to-nix.com//start/nix-run 이전 섹션에서는 [Determinate Nix Installer][nix-installer]를 사용하여 Nix를 설치했습니다. 이제 본격적으로 Nix를 사용하여 실제 프로그램을 실행해 보겠습니다. 유쾌한 [ponysay]를 실행해 봅시다: ```shell title="Pass a string to Ponysay" echo "Hello Nix" | nix run "https://flakehub.com/f/NixOS/nixpkgs/*#ponysay" ``` :rocket: **성공**입니다! 콘솔에 귀여운 조랑말의 인사가 표시될 것입니다. `nix run`을 사용하여 프로그램을 처음 실행할 때는 속도가 느릴 가능성이 높습니다. Nix가 프로그램의 [패키지][packages]를 처음부터 빌드하거나—알려진 [캐시][cache]에서 다운로드하여—[Nix 스토어][store]에 저장해야 하기 때문입니다. 이는 tarball 같은 미리 빌드된 아카이브를 다운로드하기 때문에 더 빠르게 설치하는 대부분의 [패키지 관리자][pkg]와 대조적입니다. Nix는 패키지를 다시 빌드할 필요가 없으므로, 이후의 `nix run` 호출은 즉시 실행될 것입니다. ## 설명 여기서 무슨 일이 일어났습니까? [Nix] CLI는 몇 가지 작업을 수행했습니다: - `nixpkgs` [플레이크 참조][ref]를 사용하여 Nix 코드를 가져오고 `ponysay` [플레이크 출력][output]을 대상으로 지정했습니다(자세한 내용은 뒤에서 다룹니다). - [`ponysay` 패키지][ponysay]를 빌드하고 그 결과를 [Nix 스토어][store]에 저장했습니다. - `ponysay` 패키지의 `bin/ponysay`에 있는 실행 파일을 실행했습니다. Nix에서 모든 프로그램은 [패키지][packages]의 일부입니다. 패키지는 [Nix 언어][derivations]를 사용하여 빌드됩니다. `ponysay` 패키지에는 프로그램이 하나(이름 역시 `ponysay`)만 있지만, 패키지에는 여러 프로그램뿐만 아니라 man 페이지, 설정 파일 등도 포함될 수 있습니다. 예를 들어 [`ffmpeg`][ffmpeg-pkg] 패키지는 [ffmpeg]와 [ffprobe]를 모두 제공합니다. [`nix run`][nix-run]에는 `nix install` 같은 명령이 전혀 필요하지 않다는 점을 눈치채셨을 것입니다. 따라서 셸 스크립트 작성이나 개발 중인 도구를 시험해 보는 등의 용도에 편리합니다. `nix run`에 대한 자세한 내용은 [Determinate Systems 블로그][blog]의 [설치 단계 없이 Nix로 소프트웨어 실행하기][nix-run-post]를 참조하십시오. **축하합니다**! 방금 Nix CLI를 사용하여 프로그램을 실행하고 Nix의 핵심 개념 몇 가지를 간단히 배웠습니다. 이제 Nix 개발 환경을 살펴볼 준비가 되었습니다. [blog]: https://determinate.systems/posts [cache]: /concepts/caching [derivations]: /concepts/nix-language#derivations [ffmpeg]: https://ffmpeg.org [ffmpeg-pkg]: https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/libraries/ffmpeg/generic.nix [ffprobe]: https://ffmpeg.org/ffprobe.html [nix]: /concepts/nix [nix-installer]: /concepts/nix-installer [nix-run]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-run [nix-run-post]: https://determinate.systems/posts/nix-run [output]: /concepts/flakes#outputs [packages]: /concepts/packages [ponysay]: https://github.com/erkin/ponysay [pkg]: /concepts/package-management [ref]: /concepts/flakes#references [store]: /concepts/nix-store --- **Nix 개발 환경 살펴보기** Published: URL: https://zero-to-nix.com//start/nix-develop 소프트웨어 개발을 위한 Nix의 핵심 기능 중 하나는 Nix [개발 환경][dev]입니다. [Nix 언어][language]를 사용하면 복잡도와 상관없이 어떤 개발 환경이든 정의할 수 있습니다. 이 내용은 조금 뒤에 다루겠지만, 지금은 Nix 개발 환경이 무엇이고 어떻게 동작하는지 감을 잡아 봅시다. [`nix develop`][nix-develop] 명령은 Nix 환경을 활성화합니다: ```shell title="Enter a Nix development environment defined in an external flake" nix develop "https://flakehub.com/f/DeterminateSystems/zero-to-nix/*#example" ``` `nix develop`으로 Nix 개발 환경을 처음 활성화할 때는 작업이 느릴 가능성이 높습니다. Nix가 환경에 포함된 모든 [패키지][packages]를 처음부터 빌드해야 하기 때문입니다. 이는 tarball 같은 미리 빌드된 아카이브를 내려받기 때문에 더 빠르게 설치하는 대부분의 [패키지 관리자][pkg]와 대조적입니다. Nix가 패키지를 다시 빌드할 필요가 없으므로 이후의 `nix develop` 실행은 훨씬 빠를 것입니다. 다음과 같은 새 셸 프롬프트가 나타날 것입니다: ```shell title="Shell prompt in the Nix development environment" (nix:zero-to-nix-env) bash-5.2$ ``` :rocket: **성공**입니다! 이제 [curl]과 [Git]이 포함된 [Bash] 환경에 들어와 있습니다. 두 가지 모두 이미 환경에 있을 수도 있지만, 무언가 새로운 일이 일어나고 있음을 확인하려면 다음 명령을 실행하십시오: ```shell title="Ensure that curl and Git are installed" type curl type git ``` 예를 들어 curl의 경우 다음과 같은 낯선 경로가 보일 것입니다(해시 부분은 여러분의 컴퓨터에서 다를 것입니다): 여기서 무슨 일이 일어났습니까? [Nix] CLI는 몇 가지 작업을 수행했습니다: - `https://flakehub.com/f/DeterminateSystems/zero-to-nix/*#example` [플레이크 참조][flakes]를 사용해 Nix 코드를 가져오고 특정 [플레이크 출력][output]을 빌드했습니다(자세한 내용은 뒤에서 다룹니다). - 환경 설정에 지정된 [패키지][packages]를 빌드했습니다(이 역시 자세한 내용은 뒤에서 다룹니다). - [Nix 스토어][store]에서 `git`과 `curl` 패키지를 찾을 수 있도록 [`PATH`][path]가 설정된 환경을 구성했습니다. Nix 개발 환경에서 제공할 수 있는 다른 두 가지는 다음과 같습니다: 1. 이 예제에는 포함되어 있지 않지만, 환경이 시작될 때마다 실행되는 임의의 셸 코드인 *셸 훅*을 정의할 수 있습니다. 셸 훅의 사용 사례 예시는 다음과 같습니다: - 환경이 활성화될 때마다 환경에 대한 정보를 콘솔에 `echo`합니다 - 검사나 린터 같은 작업을 실행합니다 - [Git 훅][hooks] 같은 다른 필요한 훅이 제대로 설정되어 있는지 확인합니다. 셸 훅 예제를 보려면 다음을 실행하십시오: ```shell title="Run a shell hook" nix develop "github:DeterminateSystems/zero-to-nix#hook" ``` 1. Nix 개발 환경은 환경 변수도 지원합니다. `echo $FUNNY_JOKE`를 실행하면 Nix 환경에서만 사용할 수 있는 (아주 재미있는) 값을 확인할 수 있습니다. 환경 변수의 사용 사례는 다음과 같습니다: - `LOG_LEVEL`이나 사용 중인 도구에 맞는 변수로 로깅 수준을 설정합니다. - `NODE_ENV`([Node.js]용) 같은 변수를 사용해 환경을 `development`, `dev` 등으로 설정합니다. 다음 섹션을 준비하기 위해 Nix 개발 환경에서 나갑시다: ```shell title="Leave the environment" exit ``` [Git]이 설치되어 있다면 `type git`을 사용해 `PATH`에서 Git의 위치를 확인하십시오. `/usr/bin/git` 같은 전역 경로에 있을 것입니다. 그리고 `echo $FUNNY_JOKE`를 다시 실행하면 빈 문자열이 출력될 것입니다(마침 여러분의 컴퓨터에 그 변수가 설정되어 있는 경우가 아니라면 말입니다!). ## 개발 환경 안에서 명령 실행하기 환경을 탐색하는 것은 재미있지만, 환경을 사용하기 위해 매번 그 안에 들어가고 싶지는 않을 것입니다. `nix develop` 명령은 `--command`(또는 `-c`) 플래그를 제공하며, 이 플래그를 사용하면 현재 환경*에서* 해당 환경을 _사용하는_ 명령을 실행할 수 있습니다. 앞서 사용한 환경에 대한 몇 가지 예시는 다음과 같습니다: ```shell title="Layer multiple environments" nix develop "https://flakehub.com/f/DeterminateSystems/zero-to-nix/*#example" --command git help nix develop "https://flakehub.com/f/DeterminateSystems/zero-to-nix/*#example" --command curl https://example.com ``` 두 경우 모두 [Nix 스토어][store]에 있는 패키지를 실행하며, 전역 환경의 것은 전혀 사용하지 않습니다. 보시다시피 Nix 개발 환경은 주변 환경(환경 변수나 `/bin`, `/usr/bin` 같은 경로 등)으로부터 격리되어 있다는 점에서 [_밀폐_][hermeticity]되어 있습니다. ## 언어별 환경 \{#language-specific-environments} [이전 섹션][last]에서 했던 것처럼, 조금 더 구체적으로 들어가 Nix가 특정 프로그래밍 환경에 어떤 이점을 줄 수 있는지 살펴봅시다. 다음 프로그래밍 언어 중 하나를 선택하십시오: 이제 용 Nix 개발 환경을 살펴봅시다: ```shell title="Explore a development environment for C++" nix develop "github:DeterminateSystems/zero-to-nix#cpp" ``` 먼저 [CMake]의 Nix 스토어 경로를 확인해 봅시다: ```shell title="Get path information for CMake" type cmake ``` 현재 CMake 버전을 확인하십시오: ```shell title="Check CMake's version" cmake --version ``` ```shell title="Explore a development environment for Haskell" nix develop "github:DeterminateSystems/zero-to-nix#haskell" ``` 먼저 [Glasgow Haskell Compiler][ghc](GHC)의 Nix 스토어 경로를 확인해 봅시다: ```shell title="See the store path for GHC" type ghc ``` 현재 GHC 버전을 확인하십시오: ```shell title="Check the GHC's version" ghc --version ``` ```shell title="Explore a development environment for JavaScript" nix develop "github:DeterminateSystems/zero-to-nix#javascript" ``` 먼저 [Node.js]의 Nix 스토어 경로를 확인해 봅시다: ```shell title="See the store path for Node.js" type node ``` 이제 Node를 사용해 프로그램을 실행하십시오: ```shell title="Check the Node.js version" node --eval "console.log('1 + 1 = ' + (1 + 1))" ``` ```shell title="Explore a development environment for Python" nix develop "github:DeterminateSystems/zero-to-nix#python" ``` 먼저 Python의 Nix 스토어 경로를 확인해 봅시다: ```shell title="See the store path for Python" type python ``` 이제 Python을 사용해 프로그램을 실행하십시오: ```shell title="Use Python to run a simple program" python -c "print(1 + 1)" ``` ```shell title="Explore a development environment for Go" nix develop "github:DeterminateSystems/zero-to-nix#go" ``` 먼저 [Go] CLI의 Nix 스토어 경로를 확인해 봅시다: ```shell title="See the store path for Go" type go ``` 이제 Go 버전을 확인하십시오: ```shell title="Check the Go version" go version ``` ```shell title="Explore a development environment for Rust" nix develop "github:DeterminateSystems/zero-to-nix#rust" ``` 먼저 [cargo]의 Nix 스토어 경로를 확인해 봅시다: ```shell title="See the store path for Cargo" type cargo ``` 이제 현재 디렉터리에 [Rust] 프로젝트를 생성하고 예제를 실행하십시오: ```shell title="Initialize a Rust project and run it" cargo init ./zero-to-nix-rs cd ./zero-to-nix-rs cargo run ``` `Hello, world!`가 출력될 것입니다. ```shell title="Explore a development environment for Scala" nix develop "github:DeterminateSystems/zero-to-nix#scala" ``` 먼저 [sbt]의 Nix 스토어 경로를 확인해 봅시다: ```shell title="See the store path for sbt" type sbt ``` 환경 안에서 sbt 버전을 확인하십시오: ```shell title="Check the sbt version" sbt --version ``` 평소처럼 `exit`를 실행하여 Nix 환경을 벗어나 원래 환경으로 돌아가십시오. ## 언어별 환경을 넘어서 [이전 섹션](#language-specific-environments)에서는 특정 프로그래밍 언어에 맞춘 Nix 환경을 살펴보았습니다. 하지만 Nix 환경은 무한히 유연하므로 원하는 패키지를 무엇이든 조합할 수 있습니다. 그 예시를 살펴봅시다: ```shell title="Activate a multi-language development environment" nix develop "https://flakehub.com/f/DeterminateSystems/zero-to-nix/*#multi" ``` 이 Nix 환경에서는 여러 도구를 사용할 수 있습니다: - [Python] - [kubectl] - [OpenTofu] - [OpenSSL] 앞의 예시와 마찬가지로 `type python`, `type kubectl` 같은 명령을 실행하면 이 도구들이 모두 `/usr/bin` 같은 곳이 아니라 [Nix 스토어][store]에서 발견된다는 것을 확인할 수 있습니다. 이 목록에는 패키지 100개도 쉽게 넣을 수 있습니다. 이는 여러분이 정하기 나름입니다. 이러한 환경을 _어떻게_ 만드는지는 아직 다루지 않겠지만, 이 가이드를 통해 Nix 개발 환경이 무엇을 제공하는지 기본적인 감을 얻으시기를 바랍니다. [direnv]는 디렉터리로 `cd`할 때마다 특정 환경 변수를 자동으로 불러오는(그리고 디렉터리에서 `cd`로 나갈 때 해당 변수를 해제하는) 인기 있는 도구입니다. direnv와 Nix를 함께 사용하면 디렉터리로 이동할 때마다 Nix 개발 환경을 자동으로 불러올 수 있어 상당히 강력합니다. 자세한 내용은 [Determinate Systems 블로그][blog]의 [Nix와 direnv로 손쉽게 만드는 개발 환경][nix-direnv]을 참조하십시오. ## 로컬 플레이크에서 \{#flake} 이 가이드의 앞부분에서는 [FlakeHub]에 있는 [플레이크][flakes]에 정의된 Nix 개발 환경을 활성화했습니다. 이런 방식으로 환경을 사용하는 것도 유용하지만, 현재 디렉터리의 로컬 플레이크에 정의된 개발 환경을 사용하는 것이 더 일반적입니다. 먼저 선호하는 언어를 알려 주십시오: 프로젝트를 시작하려면 빈 디렉터리를 만들고 [플레이크 템플릿][templates]을 초기화하십시오: ```shell title="Initialize a flake template for C++" mkdir nix-cpp-dev && cd nix-cpp-dev nix flake init --template "github:DeterminateSystems/zero-to-nix#cpp-dev" ``` ```shell title="Initialize a flake template for Haskell" mkdir nix-haskell-dev && cd nix-haskell-dev nix flake init --template "github:DeterminateSystems/zero-to-nix#haskell-dev" ``` ```shell title="Initialize a flake template for JavaScript" mkdir nix-javascript-dev && cd nix-javascript-dev nix flake init --template "github:DeterminateSystems/zero-to-nix#javascript-dev" ``` ```shell title="Initialize a flake template for Python" mkdir nix-python-dev && cd nix-python-dev nix flake init --template "github:DeterminateSystems/zero-to-nix#python-dev" ``` ```shell title="Initialize a flake template for Go" mkdir nix-go-dev && cd nix-go-dev nix flake init --template "github:DeterminateSystems/zero-to-nix#go-dev" ``` ```shell title="Initialize a flake template for Rust" mkdir nix-rust-dev && cd nix-rust-dev nix flake init --template "github:DeterminateSystems/zero-to-nix#rust-dev" ``` ```shell title="Initialize a flake template for Scala" mkdir nix-scala-dev && cd nix-scala-dev nix flake init --template "github:DeterminateSystems/zero-to-nix#scala-dev" ``` 템플릿이 초기화되면 `ls .`를 실행하여 디렉터리의 내용을 확인하십시오. 다음 두 가지 중요한 파일이 있어야 합니다: - `flake.nix` 파일은 프로젝트의 [플레이크][flakes]를 정의합니다. - `flake.lock`은 `flake.nix` 파일에 있는 모든 [플레이크 입력][inputs]—본질적으로 Nix 의존성—을 특정 [Git 리비전][rev]으로 [고정][pinning]합니다. 이 Nix [플레이크][flakes]의 [플레이크 출력][output] 중 하나는 용 [개발 환경][dev]입니다. 해당 개발 환경에 들어가려면 다음을 실행하십시오: ```shell title="Enter a development environment in the current flake" nix develop ``` 이제 개발 환경에 들어왔으니 [Nix 스토어 경로][paths]부터 시작하여 몇 가지를 살펴보겠습니다. 일반적으로 Unix 시스템에서 `type gcc`를 실행하면 `/usr/bin/gcc` 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오: ```shell title="Get information about the gcc executable" type gcc ``` 다음과 같은 (다소 이상한) 경로가 보일 것입니다: ```shell title="Path information for gcc" gcc is /nix/store/nbrvvx1gyq3as3ghmjz62wlgd8f3zfpf-gcc-wrapper-11.3.0/bin/gcc ``` 일반적으로 Unix 시스템에서 `type ghc`를 실행하면 `/usr/bin/ghc` 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오: ```shell title="Get path information for ghc" type ghc ``` 다음과 같은 (다소 이상한) 경로가 보일 것입니다: ```shell title="Path information for ghc" ghc is /nix/store/f3qnvw5gxgxxpr275kf97pfcy2n1gv79-ghc-9.2.4/bin/ghc ``` 일반적으로 Unix 시스템에서 `type node`를 실행하면 `/usr/bin/node` 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오: ```shell title="Get path information for Node.js" type node ``` 다음과 같은 (다소 이상한) 경로가 보일 것입니다: ```shell title="Path information for Node.js" node is /nix/store/i88kh2fd03f5fsd3a948s19gliggd2wd-nodejs-18.12.1/bin/node ``` 일반적으로 Unix 시스템에서 `type python`을 실행하면 `/usr/bin/python` 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오: ```shell title="Get path information for Python" type python ``` 다음과 같은 (다소 이상한) 경로가 보일 것입니다: ```shell title="Path information for Python" python is /nix/store/a9mmam4km4bjnkzl62533w7d0wyrhrj9-python3-3.13.6/bin/python ``` 일반적으로 Unix 시스템에서 `type go`를 실행하면 `/usr/bin/go` 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오: ```shell title="Get path information for Go" type go ``` 다음과 같은 (다소 이상한) 경로가 보일 것입니다: ```shell title="Path information for Go" go is /nix/store/5bcx8rv6sy33xsf5dzkp9q8lfdqrsiwa-go-1.19.4/bin/go ``` 일반적으로 Unix 시스템에서 `type cargo`를 실행하면 `/usr/bin/cargo` 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오: ```shell title="Get path information for cargo" type cargo ``` 다음과 같은 (다소 이상한) 경로가 보일 것입니다: ```shell title="Path information for cargo" cargo is /nix/store/zc1nr87147gvmg5nqci8q5cfnzg82vwp-rust-default-1.64.0/bin/cargo ``` 일반적으로 Unix 시스템에서 `type sbt`를 실행하면 `/usr/bin/sbt` 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오: ```shell title="Get path information for sbt" type sbt ``` 다음과 같은 (다소 이상한) 경로가 보일 것입니다: ```shell title="Path information for sbt" sbt is /nix/store/p0hca7x8g45p5hnh0xjzy5s2bcpy1i9l-sbt-1.7.3/bin/sbt ``` 아마 예상하신 결과는 아닐 것입니다! 여기서 무슨 일이 일어났습니까? 몇 가지 일이 일어났습니다: - Nix는 개발 환경에 어떤 [Nix 패키지][packages]를 포함할지 알아내기 위해 `flake.nix`의 `devShells` [플레이크 출력][output]을 살펴보았습니다(구체적으로는 `packages` 배열을 살펴보았습니다). - Nix는 `packages` 아래에 지정된 패키지를 빌드하여 `/nix/store` 아래의 [Nix 스토어][store]에 저장했습니다. [bash]: https://gnu.org/software/bash [blog]: https://determinate.systems/posts [cargo]: https://doc.rust-lang.org/stable/cargo [cmake]: https://cmake.org [curl]: https://curl.se [dev]: /concepts/dev-env [direnv]: https://direnv.net [flakehub]: https://flakehub.com [flakes]: /concepts/flakes [ghc]: https://haskell.org/ghc [git]: https://git-scm.com [go]: https://go.dev [hermeticity]: /concepts/hermeticity [hooks]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks [inputs]: /concepts/flakes#inputs [kubectl]: https://kubernetes.io/docs/reference/kubectl [language]: /concepts/nix-language [last]: /start/nix-run [nix]: /concepts/nix [nix-develop]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-develop [nix-direnv]: https://determinate.systems/posts/nix-direnv [node.js]: https://nodejs.org [openssl]: https://openssl.org [opentofu]: https://opentofu.org [output]: /concepts/flakes#outputs [packages]: /concepts/packages [path]: https://en.wikipedia.org/wiki/PATH_(variable) [paths]: /concepts/nix-store#store-paths [pinning]: /concepts/pinning [pkg]: /concepts/package-management [python]: https://python.org [rev]: https://git-scm.com/docs/revisions [rust]: https://rust-lang.org [sbt]: https://scala-sbt.org [store]: /concepts/nix-store [templates]: /concepts/flakes#templates --- **Nix로 패키지 빌드하기** Published: URL: https://zero-to-nix.com//start/nix-build [Nix]는 여러 가지 일을 할 수 있지만, 아마도 가장 잘 알려진 것은 [패키지 관리][pkg]일 것입니다. 이 튜토리얼에서는 [설치한 Nix CLI][install]를 사용해 [Nixpkgs]에 포함된 몇 가지 Nix [패키지][packages]를 빌드하고 실행해 보겠습니다. 가이드 후반부에서는 로컬 [플레이크][flake]에 정의된 Nix 패키지를 빌드하고 실행해 보겠습니다. ## Nixpkgs에서 패키지 빌드하기 \{#nixpkgs} 먼저 빈 디렉터리에서 [bat]을 빌드해 봅시다. bat은 [Rust]로 작성된 [cat]의 구문 강조 버전이며, [Nixpkgs]에 Nix 패키지가 정의되어 있습니다(반드시 쓰기 권한이 있는 디렉터리에서 실행하십시오): ```shell title="Build the bat package locally" mkdir build-nix-package && cd build-nix-package nix build "https://flakehub.com/f/NixOS/nixpkgs/*#bat" ``` 여기서 `nixpkgs`는 GitHub의 [NixOS/nixpkgs][nixpkgs-repo] 저장소를 가리키는 [플레이크 참조][ref]이고, `#bat`은 Nixpkgs 플레이크의 `bat` 출력을 빌드한다는 뜻입니다. 빌드가 끝나면 `ls .`을 실행하십시오. 현재 디렉터리에 `result`라는 항목이 보일 것입니다. `result`는 사실 [Nix 스토어][store]에 있는 빌드된 패키지를 가리키는 [심볼릭 링크][symlink]이며, 다음과 같이 확인할 수 있습니다: ```shell title="Display the Nix store path for the build result" readlink result ``` 다음과 같은 경로가 보일 것입니다(사용하는 컴퓨터에서는 조금 다를 수 있습니다): 여기서 Nix CLI가 수행한 작업은 다음과 같습니다: - [Nixpkgs]의 Nix 코드를 다운로드했습니다 - 이름이 `bat`인 패키지 정의를 찾았습니다(코드는 [이 저장소에][nixpkgs-bat] 있습니다) - `bat`의 빌드 지침을 사용해 [패키지][packages]를 빌드했습니다 - Nix의 해시 기반 경로 시스템을 사용해 결과를 [Nix 스토어][store]에 저장했습니다 {/* TODO: add substitution here and link to future caching doc */} 이제 bat을 실행할 수 있습니다: ```shell title="Run bat from the local build result" ./result/bin/bat --help ``` :rocket: **성공**입니다! Nix로 패키지를 빌드하고 실행했습니다. ### `$LANGUAGE`로 작성된 도구의 패키지 빌드하기 \{#language-specific} Nix의 큰 장점 중 하나는 패키지 빌드가 매우 유연하다는 점이며, 덕분에 거의 모든 프로그래밍 언어로 작성된 대상의 패키지를 만들 수 있습니다. 이 섹션에서는 다양한 언어로 작성된 도구의 패키지를 빌드하고 실행하면서 이를 살펴보겠습니다. 아래에서 하나를 선택해 몇 가지 예시를 확인하십시오: [CMake]를 빌드하고 실행해 봅시다: ```shell title="Build and then run CMake" nix build "nixpkgs#cmake" ./result/bin/cmake --help ``` [Pandoc]을 빌드하고 실행해 봅시다: ```shell title="Build and then run Pandoc" nix build "nixpkgs#pandoc" ./result/bin/pandoc --version ``` [npm]을 빌드하고 실행해 봅시다: ```shell title="Build and then run npm" nix build "nixpkgs#nodePackages.npm" ./result/bin/npm --help ``` `ls result/bin`을 실행하면 패키지에 [npx]도 포함되어 있음을 알 수 있습니다. [pip]을 빌드하고 실행해 봅시다: ```shell title="Build and then run pip" nix build "nixpkgs#python3Packages.pip" ./result/bin/pip --help ``` [kubectl]을 빌드하고 실행해 봅시다: ```shell title="Build and then run kubectl" nix build "nixpkgs#kubectl" ./result/bin/kubectl --help ``` [ripgrep]을 빌드하고 실행해 봅시다: ```shell title="Build and then run ripgrep" nix build "nixpkgs#ripgrep" ./result/bin/rg --help ``` [scalafmt]를 빌드하고 실행해 봅시다: ```shell title="Build and then run scalafmt" nix build "nixpkgs#scalafmt" ./result/bin/scalafmt --version ``` ### Nixpkgs 너머로 [Nixpkgs]는 알려진 우주에서 단연 가장 큰 Nix 패키지 저장소이지만, 어떤 [Nix 플레이크][flake]든 패키지 [출력][outputs]을 포함할 수 있습니다. 이번에는 다른 저장소의 패키지를 빌드해 봅시다. 홈 환경을 설정하는 데 널리 쓰이는 Nix 도구인 [Home Manager][hm]의 패키지입니다: ```shell title="Build Home Manager" nix build "https://flakehub.com/f/nix-community/home-manager/*" ``` 여기서 `https://flakehub.com/f/nix-community/home-manager/*`는 FlakeHub에 있는 [nix-community/home-manager][hm] 저장소를 가리키는 플레이크 참조입니다. Home Manager를 실행하려면 다음과 같이 하십시오: ```shell title="Run Home Manager from the build result" ./result/bin/home-manager --help ``` 패키지를 Nixpkgs 업스트림에 올리는 방법도 언제든 선택할 수 있지만, Nix를 사용하면 [`flake.nix`][flake]가 있는 공개 Git 저장소라면 어디서든 패키지를 배포할 수 있다는 점을 기억해 두면 좋습니다. ## 로컬 플레이크에서 패키지 빌드하기 \{#flake} 이 가이드의 [앞부분](#nixpkgs)에서는 [Nixpkgs]에 정의된 Nix 패키지를 빌드하면서 그 과정이 어떻게 작동하는지 대략 살펴보았습니다. 이 가이드에서는 조금 더 깊이 들어가 로컬 [Nix 플레이크][flake]에 정의된 Nix 패키지를 빌드해 보겠습니다. 앞에서와 같이 원하는 언어를 선택하십시오: 프로젝트를 시작하려면 빈 디렉터리를 만들고 [플레이크 템플릿][templates]을 초기화하십시오: ```shell title="Initialize a flake template for C++" mkdir nix-cpp-pkg && cd nix-cpp-pkg nix flake init --template "github:DeterminateSystems/zero-to-nix#cpp-pkg" ``` ```shell title="Initialize a flake template for Haskell" mkdir nix-haskell-pkg && cd nix-haskell-pkg nix flake init --template "github:DeterminateSystems/zero-to-nix#haskell-pkg" ``` ```shell title="Initialize a flake template for JavaScript" mkdir nix-javascript-pkg && cd nix-javascript-pkg nix flake init --template "github:DeterminateSystems/zero-to-nix#javascript-pkg" ``` ```shell title="Initialize a flake template for Python" mkdir nix-python-pkg && cd nix-python-pkg nix flake init --template "github:DeterminateSystems/zero-to-nix#python-pkg" ``` ```shell title="Initialize a flake template for Go" mkdir nix-go-pkg && cd nix-go-pkg nix flake init --template "github:DeterminateSystems/zero-to-nix#go-pkg" ``` ```shell title="Initialize a flake template for Rust" mkdir nix-rust-pkg && cd nix-rust-pkg nix flake init --template "github:DeterminateSystems/zero-to-nix#rust-pkg" ``` ```shell title="Initialize a flake template for Scala" mkdir nix-scala-pkg && cd nix-scala-pkg nix flake init --template "github:DeterminateSystems/zero-to-nix#scala-pkg" ``` 어떤 언어를 선택했든 다음 명령을 실행하면 로컬 플레이크에 정의된 [Nix 패키지][packages]를 빌드할 수 있습니다: ```shell title="Build a Nix package in the local flake" nix build ``` 이 명령은 로컬 플레이크에 패키지를 빌드하는 방법을 정의한 [패키지 출력][outputs]이 있는지 확인합니다. 이 플레이크에는 `default` 패키지가 있으므로 출력을 지정하지 않고도 `nix build`를 실행할 수 있지만, 예를 들어 패키지가 `packages.mypkg`로 출력된다면 이를 빌드하기 위해 `nix build .#mypkg`를 실행해야 합니다. C++ 패키지를 빌드하는 패키지 정의는 다음과 같습니다: ```nix title="flake.nix" { packages = forAllSystems ({ pkgs }: { default = let binName = "zero-to-nix-cpp"; cppDependencies = with pkgs; [ boost gcc poco ]; in pkgs.stdenv.mkDerivation { name = "zero-to-nix-cpp"; src = self; buildInputs = cppDependencies; buildPhase = "c++ -std=c++17 -o ${binName} ${./main.cpp} -lPocoFoundation -lboost_system"; installPhase = '' mkdir -p "$out/share" cp -R dist/. "$out/share"/ ''; }; }); } ``` 전체 플레이크는 GitHub의 [`flake.nix`][flake-cpp]를 참고하거나 `cat flake.nix`를 실행해 확인하십시오. 여기에 보이는 것은 패키지를 빌드하는 방법을 정의하는 [derivation]이며, 더 구체적으로는 Nix의 [표준 환경][stdenv]이 제공하는 `mkDerivation` 함수입니다. `nix build`를 실행해 만들어지는 패키지는 메시지를 출력하는 CLI 도구입니다. 이 도구를 실행하려면 다음과 같이 하십시오: ```shell title="Run the compiled binary" ./result/bin/zero-to-nix-cpp ``` 다음과 같은 출력이 나타나야 합니다: ```shell title="Expected output" Hello from Nix + C++! ``` Haskell 패키지를 빌드하는 패키지 정의는 다음과 같습니다: ```nix title="flake.nix" { packages = forAllSystems ({ pkgs }: { default = pkgs.haskellPackages.mkDerivation { pname = "zero-to-nix-haskell"; version = "0.1.0"; src = self; license = pkgs.lib.licenses.cc-by-sa-40; executableHaskellDepends = with pkgs.haskellPackages; [ base ]; }; }); } ``` 전체 플레이크는 GitHub의 [`flake.nix`][flake-haskell]를 참고하거나 `cat flake.nix`를 실행해 확인하십시오. 여기에 보이는 것은 패키지를 빌드하는 방법을 정의하는 [derivation]이며, 더 구체적으로는 [Nixpkgs]가 제공하는 [`haskellPackages.developPackage`][haskell-pkg-func] 함수입니다. `nix build`를 실행해 만들어지는 패키지는 메시지를 출력하는 CLI 도구입니다. 이 도구를 실행하려면 다음과 같이 하십시오: ```shell title="Run the compiled binary" ./result/bin/zero-to-nix-haskell ``` 다음과 같은 출력이 나타나야 합니다: ```shell title="Expected output" Hello from inside a Haskell program built with Nix! ``` JavaScript 패키지를 빌드하는 패키지 정의는 다음과 같습니다: ```nix title="flake.nix" { packages = forAllSystems ({ pkgs }: { default = pkgs.buildNpmPackage { name = "zero-to-nix-javascript"; buildInputs = with pkgs; [ nodejs_latest ]; src = self; npmDeps = pkgs.importNpmLock { npmRoot = ./.; }; npmConfigHook = pkgs.importNpmLock.npmConfigHook; installPhase = '' mkdir $out cp dist/index.html $out ''; }; }); } ``` 전체 플레이크는 GitHub의 [`flake.nix`][flake-js]를 참고하거나 `cat flake.nix`를 실행해 확인하십시오. 여기에 보이는 것은 패키지를 빌드하는 방법을 정의하는 [derivation]이며, 더 구체적으로는 Nix에 내장된 derivation 함수를 감싸는 래퍼인 `buildNpmPackage` 함수입니다. `nix build`를 실행해 만들어지는 패키지는 [Vite] 프레임워크로 빌드한 웹사이트입니다. 이 웹사이트를 보려면 `result/share/index.html`에 있는 HTML 파일을 여십시오. 다음은 Python 패키지를 빌드할 수 있게 해 주는 패키지 정의입니다: ```nix title="flake.nix" { packages = forAllSystems ({ pkgs }: { default = let python = pkgs.python3; in python.pkgs.buildPythonApplication { name = "zero-to-nix-python"; buildInputs = with python.pkgs; [ pip ]; src = ./.; }; }); } ``` 전체 플레이크는 GitHub의 [`flake.nix`][flake-py]를 참고하거나 `cat flake.nix`를 실행하십시오. 여기에서 보이는 것은 패키지를 빌드하는 방법을 정의하는 [derivation]이며, 더 구체적으로는 Nix의 내장 함수인 `derivation`을 감싼 래퍼인 [`buildPythonApplication`][buildpythonapplication] 함수입니다. 이렇게 만들어진 패키지는 터미널에 출력하는 실행 파일입니다. 패키지를 실행하려면 다음과 같이 하십시오: ```shell title="Run the built executable" ./result/bin/zero-to-nix-python ``` 다음과 같은 터미널 출력이 표시되어야 합니다: ```text Hello from inside a Python program built with Nix! ``` 다음은 이 Go 패키지를 빌드할 수 있게 해 주는 패키지 정의입니다: ```nix title="flake.nix" { packages = forAllSystems ({ pkgs }: { default = pkgs.buildGoModule { name = "zero-to-nix-go"; src = self; vendorHash = "sha256-Ay1/QqbO2MyYgqJZKxrt1FZzLSgXbhSK3ceFPUlFujw="; goSum = ./go.sum; subPackages = [ "cmd/zero-to-nix-go" ]; }; }); } ``` 전체 플레이크는 GitHub의 [`flake.nix`][flake-go]를 참고하거나 `cat flake.nix`를 실행하십시오. 여기에서 보이는 것은 패키지를 빌드하는 방법을 정의하는 [derivation]이며, 더 구체적으로는 Nix의 내장 함수인 `derivation`을 감싼 래퍼인 [`buildGoModule`][buildgomodule] 함수입니다. `nix build`를 실행하면 만들어지는 패키지는 [Gin] 프레임워크로 만든 웹 서버입니다. 패키지를 실행하려면 다음과 같이 하십시오: ```shell title="Run the compiled binary" ./result/bin/zero-to-nix-go ``` 다른 창에서 `curl http://localhost:8080`을 실행하면 서버로부터 메시지를 받을 수 있습니다. 다음은 이 Rust 패키지를 빌드할 수 있게 해 주는 패키지 정의입니다: ```nix title="flake.nix" { packages = forAllSystems ({ pkgs }: { default = let rustPlatform = pkgs.makeRustPlatform { cargo = pkgs.rustToolchain; rustc = pkgs.rustToolchain; }; in rustPlatform.buildRustPackage { name = "zero-to-nix-rust"; src = ./.; cargoLock = { lockFile = ./Cargo.lock; }; }; }); } ``` 전체 플레이크는 GitHub의 [`flake.nix`][flake-rs]를 참고하거나 `cat flake.nix`를 실행하십시오. 여기에서 보이는 것은 패키지를 빌드하는 방법을 정의하는 [derivation]이며, 더 구체적으로는 Nix의 내장 함수인 `derivation`을 감싼 래퍼인 [`buildRustPackage`][buildrustpackage] 함수입니다. 터미널에 출력하는 실행 파일인 결과 패키지를 실행하려면 다음과 같이 하십시오: ```shell title="Run the compiled binary" ./result/bin/zero-to-nix-rust ``` 다음과 같은 터미널 출력이 표시되어야 합니다: ```text Hello from Nix + Rust! ``` 솔직히 말씀드리면 [Scala]를 패키징하는 것은 꽤 까다롭습니다. 다행히 [`sbt-derivation`][sbt-derivation]이라는 서드파티 프로젝트가 몇 가지 유용한 헬퍼를 제공하며, 그중에는 Nix의 내장 함수인 `derivation`을 감싼 래퍼인 `mkSbtDerivation`이라는 편리한 함수도 있습니다. 이 패키지의 전체 플레이크는 GitHub의 [`flake.nix`][flake-scala]를 참고하거나 `cat flake.nix`를 실행하십시오. 터미널에 출력하는 실행 파일인 결과 패키지를 실행하려면 다음과 같이 하십시오: ```shell title="Run the built executable" ./result/bin/zero-to-nix-scala ``` 다음과 같은 터미널 출력이 표시되어야 합니다: ```text Hello from Nix + Scala! ``` 여기에서는 [derivation][derivation]과 직접 패키지를 만드는 방법을 더 깊이 다루지 않겠지만, 이 가이드를 통해 Nix 코드가 실제 빌드 출력으로 바뀌는 과정을 이해하셨기를 바랍니다. [bat]: https://github.com/sharkdp/bat [buildgomodule]: https://nixos.org/manual/nixpkgs/stable/#ssec-language-go [buildpythonapplication]: https://nixos.org/manual/nixpkgs/stable/#buildpythonapplication-function [buildrustpackage]: https://nixos.org/manual/nixpkgs/stable/#rust [cat]: https://en.wikipedia.org/wiki/Cat_(Unix) [cmake]: https://cmake.org [derivation]: /concepts/derivations [flake]: /concepts/flakes [flake-cpp]: https://github.com/DeterminateSystems/zero-to-nix/tree/main/nix/templates/pkg/cpp/flake.nix [flake-go]: https://github.com/DeterminateSystems/zero-to-nix/tree/main/nix/templates/pkg/golang/flake.nix [flake-haskell]: https://github.com/DeterminateSystems/zero-to-nix/tree/main/nix/templates/pkg/haskell/flake.nix [flake-js]: https://github.com/DeterminateSystems/zero-to-nix/tree/main/nix/templates/pkg/javascript/flake.nix [flake-py]: https://github.com/DeterminateSystems/zero-to-nix/tree/main/nix/templates/pkg/python/flake.nix [flake-rs]: https://github.com/DeterminateSystems/zero-to-nix/tree/main/nix/templates/pkg/rust/flake.nix [flake-scala]: https://github.com/DeterminateSystems/zero-to-nix/tree/main/nix/templates/pkg/scala/flake.nix [gin]: https://github.com/gin-gonic/gin [haskell-pkg-func]: https://haskell4nix.readthedocs.io [hm]: https://github.com/nix-community/home-manager [install]: /start/install [kubectl]: https://github.com/kubernetes/kubectl [nix]: /concepts/nix [nixpkgs]: /concepts/nixpkgs [nixpkgs-bat]: https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/ba/bat/package.nix [nixpkgs-repo]: https://github.com/NixOS/nixpkgs [npm]: https://npmjs.com [npx]: https://docs.npmjs.com/cli/v8/commands/npx [outputs]: /concepts/flakes#outputs [packages]: /concepts/packages [pandoc]: https://pandoc.org [pkg]: /concepts/package-management [pip]: https://pypi.org/project/pip [ref]: /concepts/flakes#references [ripgrep]: https://github.com/BurntSushi/ripgrep [rust]: https://rust-lang.org [sbt-derivation]: https://github.com/zaninime/sbt-derivation [scala]: https://scala-lang.org [scalafmt]: https://scalameta.org/scalafmt [stdenv]: https://nixos.org/manual/nixpkgs/stable/#chap-stdenv [store]: /concepts/nix-store [symlink]: https://en.wikipedia.org/wiki/Symbolic_link [templates]: /concepts/flakes#templates --- **Nix 패키지 검색하기** Published: URL: https://zero-to-nix.com//start/nix-search Nix의 큰 장점 중 하나는 [Nix 개발 환경][env], [NixOS][nixos] 설치 등에서 사용할 수 있는 [패키지][packages]가 [Nix 생태계][ecosystem]에 *엄청나게* 많다는 점입니다. [Nixpkgs]는 단연 가장 큰 Nix 패키지 모음이지만(10만 개가 넘는 패키지가 있으며 지금도 늘어나고 있습니다 :sunglasses:), 어떤 [Nix 플레이크][flakes]든 패키지 [출력][outputs]을 제공할 수 있습니다. 하지만 이렇게 방대한 패키지를 탐색하는 일은 까다로울 수 있으므로, 이 가이드에서는 [`nix search`][nix-search] 명령과 [search.nixos.org][search]의 웹 애플리케이션을 사용하여 Nixpkgs에서 패키지를 검색하는 방법을 알아보겠습니다. 그런 다음 [다른 플레이크](#nix-flake-show)의 패키지를 살펴보는 방법을 알아보겠습니다. ## `nix search` 명령 \{#nix-search-command} [Nix CLI][nix]에는 검색어를 바탕으로 플레이크의 패키지를 검색할 수 있는 `search` 명령이 있습니다. 원하는 패키지를 찾을 가능성이 가장 높은 [Nixpkgs]를 검색하는 것부터 시작합시다. 이 명령은 [Nixpkgs]에 [cargo]가 있는지 알려 줍니다: ```shell title="Search Nixpkgs using cargo as the search term" nix search "https://flakehub.com/f/NixOS/nixpkgs/*" cargo ``` 이 명령에서 `nixpkgs` [플레이크 참조][flake-ref]는 `github:NixOS/nixpkgs`의 약칭입니다. `nix search`를 처음 실행하면 Nix CLI는 [Nixpkgs][Nixpkgs](또는 검색 중인 플레이크)의 Nix 코드 전체를 다운로드한 다음 캐시해야 합니다. 이후 Nixpkgs에 대한 `nix search` 실행은 훨씬 빨라집니다. 게다가 Nixpkgs는 현존하는 가장 큰 플레이크이므로, 다른 플레이크에서 `nix search`를 실행하면 일반적으로 훨씬 빠릅니다. 이 명령은 `legacyPackages.{system}.{package}` 형식의 결과를 많이 보여 주며, Apple Silicon(`aarch64-darwin`) 시스템에서는 그중 첫 번째 결과가 다음과 같이 표시됩니다: ```shell title="Example search result" * legacyPackages.aarch64-darwin.cargo (1.65.0) Downloads your Rust project's dependencies and builds your project ``` 시스템 속성은 다른 플랫폼에서는 [달라집니다](#system-specificity)(`x86_64-linux` 또는 다른 값이 표시될 수 있습니다). 첫 번째 결과 다음에는 [`cargo-about`][cargo-about]와 [`cargo-audit`][cargo-audit] 같은 패키지를 포함하여 많은 결과가 표시됩니다. 검색 출력에 보이는 `legacyPackages` 속성은 다소 오해의 소지가 있습니다. 이 접두사가 붙은 [패키지][packages]는 "레거시" 패키지가 아닙니다. [Nixpkgs]는 [이 코드 주석][legacy-comment]에 설명된 이유로 일반적인 `packages` 출력 대신 특별한 `legacyPackages` 속성을 사용하여 패키지를 출력합니다. `--json` 플래그를 사용하여 검색 결과를 JSON으로 출력할 수도 있습니다: ```shell title="Output search results as JSON" nix search --json nixpkgs cargo ``` 이는 [jq] 같은 도구로 출력을 파싱하려는 경우에 유용합니다. ## search.nixos.org \{#web} [search.nixos.org][search]의 웹 인터페이스는 [`nix search`](#nix-search-command) 명령에 비해 몇 가지 장점이 있습니다: - [25.05]나 [unstable] 같은 [Nixpkgs] 릴리스 채널을 선택할 수 있습니다 - Nixpkgs 외에도 다양한 [공개 플레이크][public-flakes]를 검색할 수 있습니다(해당 플레이크 목록은 [Nix 매뉴얼][flakes-list]에 있습니다) ## `nix flake show` 명령으로 플레이크 살펴보기 \{#nix-flake-show} 예시로 [Wayland] 윈도 시스템 프로토콜을 위한 인기 있는 플레이크를 살펴봅시다. ```shell title="Display the flake outputs for the nixpkgs-wayland flake" nix flake show "github:nix-community/nixpkgs-wayland" ``` 출력을 JSON으로 표시할 수도 있습니다: ```shell title="Display the flake outputs for the nixpkgs-wayland flake as JSON" nix flake show --json "github:nix-community/nixpkgs-wayland" ``` `nix flake show`를 처음 실행하면 Nix CLI는 [`nixpkgs-wayland`][nixpkgs-wayland](또는 `nix flake show`를 실행하는 대상 플레이크)의 전체 내용을 다운로드한 뒤 캐시해야 합니다. 이후 같은 [플레이크 참조][flake-ref]에 대해 `nix flake show`를 실행하면 훨씬 빨라집니다. `nix flake show`와 `nix search` 중 어느 것을 사용해야 합니까? 좋은 경험칙은 Nixpkgs에는 항상 `nix search`를 사용하고, 다른 플레이크에는 우선 `nix flake show`를 사용하는 것입니다. `nix flake show`의 패키지 출력이 살펴보기 까다로울 만큼 크다면, 해당 플레이크에는 대신 `nix search`를 사용하십시오. ## 시스템 특정성 `nix search`, [search.nixos.org][search], `nix flake show`의 검색 출력을 보면, 조회 결과에 나열된 모든 패키지가 현재 시스템(AMD/Intel Linux 시스템이라면 `x86_64-linux`, Apple Silicon 시스템이라면 `aarch64-darwin` 등)용이라는 점을 알 수 있습니다. 이는 Nix가 근본적으로 [시스템별][system-specific] 방식으로 동작하기 때문입니다. Linux 머신의 `cargo` 패키지는 Linux가 아닌 시스템의 `cargo`와 *서로 다른 패키지*로 간주됩니다. [25.05]: https://github.com/nixOS/nixpkgs/tree/25.05 [cargo]: https://github.com/rust-lang/cargo [cargo-about]: https://github.com/EmbarkStudios/cargo-about [cargo-audit]: https://github.com/RustSec/rustsec/tree/main/cargo-audit [ecosystem]: /concepts/ecosystem [env]: /concepts/dev-env [flake-ref]: /concepts/flakes#references [flakes]: /concepts/flakes [flakes-list]: https://github.com/NixOS/nixos-search/blob/main/flakes/manual.toml [jq]: https://stedolan.github.io/jq [legacy-comment]: https://github.com/NixOS/nixpkgs/blob/fcc8ff7cc271c9652623dae2a9fcd1ba49232b57/flake.nix#L47-L55 [nix]: /concepts/nix [nix-search]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-search [nixos]: /concepts/nixos [nixpkgs]: /concepts/nixpkgs [nixpkgs-wayland]: https://github.com/nix-community/nixpkgs-wayland [outputs]: /concepts/flakes#outputs [packages]: /concepts/packages [public-flakes]: https://search.nixos.org/flakes [search]: https://search.nixos.org [system-specific]: /concepts/system-specificity [unstable]: https://github.com/nixOS/nixpkgs/tree/nixpkgs-unstable [wayland]: https://wayland.freedesktop.org --- **프로젝트를 플레이크로 전환하기** Published: URL: https://zero-to-nix.com//start/init-flake Zero to Nix의 이전 단계 중 일부에서 [Nix 플레이크][flakes]와 Nix [개발 환경][dev-env]에 대해 배웠습니다. 직접 만든 프로젝트를 플레이크로 전환하는 일은 다소 까다로울 수 있으므로, 저희 [Determinate Systems][detsys]는 여러 상황에서 도움이 되는 도구를 만들었습니다. 바로 [FlakeHub] 플랫폼용 CLI인 [`fh`][fh]입니다. `fh`에는 [`fh init`][fh-init]이라는 유틸리티가 있으며, 이 유틸리티는 다음 두 가지를 바탕으로 `flake.nix` 파일을 생성합니다: 1. 프로젝트의 내용 1. 대화형 질문에 대한 여러분의 응답 Nix를 사용하여 `fh init`을 실행할 수 있습니다: ```shell title="Initialize your flake" nix run "https://flakehub.com/f/DeterminateSystems/fh/*" -- init ``` 이 명령은 일련의 질문을 하는 대화형 빌더를 시작한 다음, 프로젝트 루트에 `flake.nix` 파일을 작성합니다(일부 질문에 예라고 답하면 다른 파일도 함께 작성합니다). 새 플레이크를 생성했다면, 해당 플레이크에 어떤 출력이 있는지 확인할 수 있습니다: ```shell title="Display the flake's outputs" nix flake show ``` 다음과 비슷한 결과가 표시될 것입니다: ```text title="Flake outputs" git+file:///path/to/fh-init-example-project ├───devShells │ ├───aarch64-darwin │ │ └───default: development environment 'nix-shell' │ ├───aarch64-linux │ │ └───default omitted (use '--all-systems' to show) │ └───x86_64-linux │ └───default omitted (use '--all-systems' to show) └───schemas: unknown ``` `fh init`은 다양한 [언어와 도구][handlers]를 지원합니다. 예를 들어 프로젝트 루트에 [`Cargo.toml`][cargo-toml] 파일이 있으면, `fh init`은 해당 프로젝트를 [Rust] 프로젝트로 추론하고 Nix [개발 환경][dev-env]에 Rust 의존성을 추가할지 묻습니다. 예라고 답하면, 생성된 `flake.nix`에는 `cargo` 빌드 도구와 그 밖의 Rust 전용 도구가 포함됩니다. `fh init`은 현재 [`devShells`][dev-env] 출력만 지원한다는 점에 유의하십시오. 즉, [패키지 출력][packages] 같은 것은 생성하지 않고 개발 환경만 생성합니다. `fh init`은 프로젝트에서 사용하는 언어와 도구를 추론할 때 "최선의 추측"에 기반하여 동작한다는 점을 알아 두십시오. 일부를 놓치거나 잘못 추측할 가능성도 있습니다. 하지만 이 도구가 생성하는 `flake.nix`가 최소한 여러분이 더 다듬어 나갈 수 있는 탄탄한 초기 템플릿 역할을 해 주기를 바랍니다. ## 예제 프로젝트 `fh init`을 시험해 볼 수 있는 예제 프로젝트를 준비했습니다: ```shell title="Test out fh init using the example project" git clone https://github.com/DeterminateSystems/fh-init-example-project cd fh-init-example-project nix run "https://flakehub.com/f/DeterminateSystems/fh/*" -- init # respond to the prompts nix flake show ``` [cargo-toml]: https://doc.rust-lang.org/cargo/reference/manifest.html [detsys]: https://determinate.systems [dev-env]: /concepts/dev-env [fh]: https://github.com/DeterminateSystems/fh [fh-init]: https://github.com/determinateSystems/fh#initialize-a-new-flakenix-from-scratch [flakehub]: /concepts/flakehub [flakes]: /concepts/flakes [handlers]: https://github.com/DeterminateSystems/fh/tree/main/src/cli/cmd/init/handlers [packages]: /concepts/packages [rust]: https://rust-lang.org --- **Nix 제거하기(필요한 경우)** Published: URL: https://zero-to-nix.com//start/uninstall Zero to Nix 빠른 시작의 첫 부분에서는 [Determinate Systems][ds]의 빠르고 안정적인 [Determinate Nix Installer][nix-installer]를 사용하여 Nix를 [설치했습니다][installed]. 앞으로도 Nix와 함께하는 여정이 오래도록 이어지기를 바라지만, 어떤 이유로든 Nix를 제거해야 한다면 다음 명령으로 제거할 수 있습니다: ```shell title="Uninstall Nix" /nix/nix-installer uninstall ``` 안내에 따라 요청된 변경 사항을 승인하십시오. 설치 프로그램이 요청하는 변경 사항 중 일부는 다음과 같습니다: - `/nix` 아래의 디렉터리 트리 삭제 - [Nix] CLI 도구 삭제 - Nix 전용 사용자 및 그룹 전체 삭제 - `/etc/nix/nix.conf`에 있는 Nix 설정 파일 삭제 Determinate Nix Installer가 완료되면 `/nix`, `~/.nix-profile` 같은 디렉터리가 시스템에서 제거되었는지 확인하여 제거가 성공했는지 검증할 수 있습니다: ```shell title="Verify that uninstallation has succeeded" ls /nix # error ls ~/.nix-profile # error ``` [ds]: https://determinate.systems [installed]: /start/install [nix]: /concepts/nix [nix-installer]: /concepts/nix-installer --- **더 알아보기** Published: URL: https://zero-to-nix.com//start/learn-more 이것으로 Zero to Nix 여정을 마칩니다! 여러분은 방금 많은 것을 해냈습니다: - 여러분은 자신의 컴퓨터에 [Nix를 설치했습니다][install] - 여러분은 Nix를 사용해 몇 가지 [프로그램][programs]을 실행했습니다 - 여러분은 몇 가지 [Nix 개발 환경][env]을 살펴보았습니다 - 여러분은 [Nixpkgs]와 Nix [생태계][ecosystem]의 다른 곳에서 패키지를 [검색했습니다][searched] - 여러분은 몇 가지 [Nix 패키지][pkg]를 빌드했습니다 이는 몇 가지 예에 불과합니다. 시간과 노력을 들여 주셔서 정말 기쁩니다. 하지만 여러분의 Nix 여정이 앞으로도 계속되기를 바랍니다. 이 가이드에서는 빠른 시작의 범위를 넘어, 새로 얻은 Nix 지식을 적용할 수 있는 몇 가지 분야를 제안합니다. ## 컨테이너 이미지 빌드하기 \{#containers} [Nix]는 [curl]과 [Git] 같은 표준 도구부터 [Vim] 플러그인, [Visual Studio Code][code] 확장, 여러분이 선호하는 언어로 작성한 웹 서비스, 그리고 그 너머에 이르기까지 수많은 것들의 [패키지][packages]를 빌드할 수 있습니다. 이 [빠른 시작][start]에서는 이러한 패키지 유형 중 몇 가지를 다루었습니다. Nix의 또 다른 강력한 기능은 [OCI] 호환 컨테이너 이미지를 빌드하는 데 사용할 수 있어, (적어도 이미지 빌드에 관해서는) [Docker]나 [Podman] 같은 도구를 대체할 수 있다는 점입니다. ## 운영 체제로 NixOS 사용하기 \{#nixos} [NixOS]는 Nix와 [재현성][reproducibility], [선언형 설정][declarative] 같은 Nix의 핵심 원칙을 기반으로 구축된 [Linux] 배포판입니다. ## 홈 환경 설정하기 \{#home-environment} [Home Manager][home]는 Nix를 기반으로 구축된 플러그인 기반 도구로, [Vim], [tmux], [Visual Studio Code][code], [Git], [gpg], 그리고 [Bash], [zsh], [fish] 같은 셸을 포함하여 홈 환경의 다양한 도구를 설정하는 데 사용할 수 있습니다. ## 지속적 통합 \{#ci} 여러분은 앞서 빠른 시작에서 [Nix 개발 환경][env]에 대해 배웠습니다. Nix 개발 환경은 크로스 플랫폼이면서 완전히 [재현 가능][reproducibility]하기 때문에 [지속적 통합][ci] 환경에서 매우 유용합니다. [bash]: https://gnu.org/software/bash [ci]: https://en.wikipedia.org/wiki/Continuous_integration [code]: https://code.visualstudio.com [curl]: https://curl.se [declarative]: /concepts/declarative [docker]: https://docker.com [ecosystem]: /concepts/ecosystem [env]: /start/nix-develop [fish]: https://fishshell.com [git]: https://git-scm.com [gpg]: https://gnupg.org [home]: https://github.com/nix-community/home-manager [install]: /start/install [linux]: https://www.kernel.org/ [nix]: /concepts/nix [nixos]: /concepts/nixos [nixpkgs]: /concepts/nixpkgs [oci]: https://opencontainers.org [packages]: /concepts/packages [pkg]: /start/nix-build [programs]: /start/nix-run [podman]: https://podman.io [reproducibility]: /concepts/reproducibility [searched]: /start/nix-search [start]: /start [tmux]: https://github.com/tmux/tmux [vim]: https://www.vim.org [zsh]: https://zsh.org --- ## Concept pages --- **캐싱** Published: URL: https://zero-to-nix.com//concepts/caching Nix는 기본적으로 *캐싱*을 사용하여 [패키지 빌드][packages]를 더 빠르고 효율적으로 만듭니다. 이는 결과적으로 [개발 환경][dev] 생성이나 [NixOS] 환경 구축처럼 패키지 빌드가 수반되는 다른 Nix 작업도 더 빠르고 효율적으로 만듭니다. ## 빌드와 캐싱 Nix가 패키지의 [derivation]을 [실체화][realising]하여 [패키지][packages]를 빌드할 때마다 해당 derivation의 [클로저][closure] 전체를 실체화해야 합니다. 즉, 패키지의 derivation을 빌드하는 데 필요한 모든 derivation과 그 derivation들을 빌드하는 데 필요한 derivation 등을 모두 실체화해야 합니다. 어떤 패키지는 클로저(의존성 트리)가 아주 작지만, 어떤 패키지는 수천 개의 derivation이 포함된 거대한 클로저를 가지므로 Nix에서는 빌드 효율성이 주요 관심사입니다. Nix가 derivation을 실체화할 때마다 수행하는 작업은 다음과 같습니다: 1. derivation의 해시를 계산하고, 그 해시를 사용하여 다음과 같은 형태의 [Nix 스토어 경로][store-paths]를 계산합니다(가상의 Git 패키지의 경우): 1. 스토어 경로를 얻으면 Nix는 해당 derivation이 이미 빌드되었는지 판단합니다. 먼저 Nix는 설정된 [Nix 스토어][store]에 `/nix/store/f8f72p3xxr20k111mpg4kk93i4cp74qb/git-2.37.0` 경로가 이미 존재하는지 확인합니다. 존재한다면 빌드하지 않고 그것을 사용합니다. 존재하지 않는다면... 1. 설정된 [바이너리 캐시](#binary-caches)에 해당 스토어 경로가 존재하는지 확인합니다. 1. 스토어 경로가 설정된 [Nix 스토어][store]에도, 설정된 [바이너리 캐시](#binary-caches)에도 존재하지 않으면, Nix는 이 목록의 모든 단계를 재귀적으로 따르면서 가능한 한 이미 실체화된 패키지를 사용하고 필요한 것만 빌드하여 derivation을 처음부터 빌드합니다. 캐싱이 없다면 [실체화][realising]할 때마다 매번 모든 것을 처음부터 빌드해야 하며, 이로 인해 Nix는 훨씬 덜 효율적인—그래서 훨씬 덜 매력적인!—패키지 관리자이자 빌드 도구가 될 것입니다. ## 바이너리 캐시 \{#binary-caches} 로컬 [Nix 스토어][store] 외에도, HTTP를 통해 미리 빌드된 바이너리를 제공하는 *바이너리 캐시*라는 원격 Nix 스토어를 사용하여 Nix 산출물을 캐시할 수도 있습니다. 대부분의 경우 바이너리 캐시는 Nix 스토어와 똑같이 동작하여, Nix가 derivation의 Nix 스토어 경로를 기준으로 무언가가 이미 빌드되었는지 빠르게 판단할 수 있게 합니다. Nix는 기본적으로 [cache.nixos.org][cache]를 바이너리 캐시로 사용합니다. 이 캐시는 누구에게나 공개되어 있으며 지속적 통합 시스템을 통해 채워집니다. 이 커뮤니티 캐시 외에도 바이너리 캐시를 [직접 운영][run]하거나 [FlakeHub Cache][flakehub-cache] 같은 바이너리 캐시 서비스를 사용할 수도 있습니다. [cache]: http://cache.nixos.org [closure]: /concepts/closures [derivation]: /concepts/derivations [dev]: /concepts/dev-env [flakehub-cache]: https://flakehub.com/cache [nixos]: /concepts/nixos [packages]: /concepts/packages [realising]: /concepts/realisation [run]: https://wiki.nixos.org/wiki/Binary_Cache [store]: /concepts/nix-store [store-paths]: /concepts/nix-store#store-paths --- **채널** Published: URL: https://zero-to-nix.com//concepts/channels *Nix 채널*은 레거시 Nix CLI가 [Nixpkgs]를 최신 상태로 유지하는 데 사용하는 메커니즘입니다. 새로운 Nix CLI에서는 채널이 [플레이크][flakes]로 대체되었습니다. ## 채널은 어떻게 작동합니까? 채널은 `https://nixos.org/channels/nixos-unstable`처럼 특정 Nix 코드를 가리키는 URL입니다. 편의를 위해 `channel:{name}` URL 구문을 사용할 수도 있으며, Nix는 이를 `https://nixos.org/channels/{name}`로 확장합니다. 다음과 같이 Nix가 채널을 자동으로 가져오도록 설정할 수 있습니다: ```shell title="Add a channel" nix-channel --add https://nixos.org/channels/nixos-unstable ``` 그런 다음 이 명령을 실행하면 Nix가 설정한 모든 채널을 가져옵니다: ```shell title="Update all channels" nix-channel --update ``` 채널의 Nix 코드는 `~/.nix-defexpr/channels`에 압축 해제되며, `nix-env` 같은 레거시 CLI 명령은 이곳에서 해당 코드를 찾을 수 있습니다. 채널에 대한 자세한 정보는 [Nix 매뉴얼][manual]에서 확인할 수 있습니다. ## 채널 예시 | 채널 URL | 릴리스 날짜 | 설명 | | ------------------------------ | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `channel:nixos-22.11` | 2022년 11월에 처음 릴리스되었으며 이후 6개월 동안 업데이트되었습니다 | 2022년 11월에 릴리스된 NixOS의 안정 버전입니다. 보안 패치와 업데이트는 백포트되지만, 새로운 애플리케이션이나 호환성을 깨는 변경 사항은 적용되지 않습니다 | | `channel:nixos-unstable` | 자주 업데이트됩니다 | 중요한 패키지 집합이 Hydra에서 빌드될 때마다 업데이트되는 NixOS의 롤링 릴리스 채널입니다. 보안 업데이트, 새 패키지, 새 모듈이 컴퓨터에 자주 반영되며, 호환성을 깨는 변경 사항이 발생할 수 있습니다 | | `channel:nixos-unstable-small` | `nixos-unstable`과 같지만 훨씬 더 자주 업데이트됩니다 | `nixos-unstable`과 비슷하지만 테스트하는 패키지 집합이 더 작은 롤링 릴리스 채널입니다. 따라서 이 채널은 더 자주 업데이트되지만, 일부 패키지가 깨져 있을 수도 있습니다 | ## `nix-channel`의 문제점 채널의 문제점은 특정 빌드에서 실제로 어떤 입력이 사용되는지 전혀 보장하지 않는다는 것입니다. `channel:nixos-22.11` 같은 채널 URL은 시점에 따라 서로 다른 Nix 코드를 담고 있을 수 있습니다. 따라서 채널을 사용하면 소스 [고정][pinning]과 롤백이 훨씬 어렵습니다. 즉, Nix는 이론적으로는 [재현 가능][reproducible]하지만 실제로는 빌드 입력이 자주 바뀔 수 있으며, 이로 인해 빌드가 실패할 수 있습니다. 이 때문에 NixOS 시스템을 업데이트하지 못하거나, 이전에는 빌드할 수 있었던 패키지를 빌드하지 못하게 될 수 있습니다. **이러한 이유로 Nix 채널 사용은 강력히 권장하지 않습니다!** [flakes]: /concepts/flakes [manual]: https://nixos.org/manual/nix/stable/command-ref/nix-channel [nixpkgs]: /concepts/nixpkgs [pinning]: /concepts/pinning [reproducible]: /concepts/reproducibility --- **클로저** Published: URL: https://zero-to-nix.com//concepts/closures Nix에서 [패키지][package]의 *클로저*는 해당 패키지를 [빌드하거나 실행](#build-vs-run)하는 데 필요한 모든 패키지(그리고 그 패키지들을 빌드하는 데 필요한 패키지 등)를 포괄합니다. 패키지를 빌드하는 데 다른 패키지가 전혀 필요하지 않아 클로저에 패키지가 하나도 없을 수도 있고, 반대로 많은 패키지가 있을 수도 있습니다. 패키지를 빌드할 때마다 Nix는 항상 [샌드박스][sandboxed] 환경에서 해당 패키지의 클로저 전체를 [실체화][realises]합니다. ## 빌드 타임 클로저와 런타임 클로저 \{#build-vs-run} Nix 클로저에는 두 가지 유형이 있습니다. - _빌드 타임_ 클로저에는 패키지를 빌드하는 데 필요한 모든 것이 포함됩니다. - _런타임_ 클로저에는 패키지를 실행하는 데 필요한 모든 것이 포함됩니다. 예를 들어, 여러분의 머신에 [Firefox]를 설치하고 실행하기 위해 Nix로 Firefox를 빌드한다고 가정해 봅시다. [GCC] 없이는 Firefox를 빌드할 수 없으므로 Firefox의 빌드 타임 클로저에는 GCC가 포함됩니다. 하지만 런타임 클로저에는 GCC가 포함되지 않습니다. Firefox는 이미 빌드되었기 때문입니다! 대신 Firefox가 사용자 인터페이스에 필요로 하는 [GTK]는 포함됩니다. Nix 문서나 다른 곳에서 Nix 클로저가 언급될 때는 대개 런타임 클로저를 의미합니다. ## 클로저 비대화 패키지에 필요하지 않은 것을 클로저에 포함하면 시간, 디스크 공간, 네트워크 대역폭과 같은 자원이 낭비되는데, 이를 *클로저 비대화*라고 합니다. Nix는 지시받은 것은 무엇이든 항상 [실체화][realises]하며, 클로저 비대화를 방지하는 내장 메커니즘이 없습니다. 클로저 비대화의 해결책은 늘 주의를 기울이는 것입니다. 직접 작성한 [derivation][derivations]을 항상 점검하여 derivation에 포함한 모든 패키지가 원하는 패키지를 빌드하거나 실행하는 데 정말로 필요한지 확인하십시오. [derivations]: /concepts/derivations [firefox]: https://mozilla.org/firefox [gcc]: https://gcc.gnu.org [gtk]: https://gtk.org [package]: /concepts/packages [realises]: /concepts/realisation [sandboxed]: /concepts/sandboxing --- **선언형 프로그래밍** Published: URL: https://zero-to-nix.com//concepts/declarative *선언형 프로그래밍*에서 사용자는 컴퓨터에 _어떻게_ 할지가 아니라 _무엇을_ 할지를 지시합니다. 그 결과, 최종 시스템은 흔히 _존재해야 하는_ 모습 그대로 기술됩니다. 그러면 관리 프로그램(여기서는 Nix)이 최종 출력에 이르는 경로를 구성하고 필요한 단계를 요구되는 순서대로 수행할 수 있으므로, 사용자는 정확히 무슨 일이 언제 일어나는지 신경 쓸 필요가 없습니다. Nix는 몇 가지 사소한 예외를 제외하면 패키지 정의(또는 [derivation](/zero-to-nix/concepts/derivations))를 구성하는 방식에서 선언형 원칙을 따릅니다. 내부적으로는 패키지의 일부를 여전히 명령형으로 작성해야 하지만, 이러한 부분을 선언형 계층으로 감싸면 상위 계층의 사용자는 그 아래에서 무슨 일이 일어나는지 알 필요가 없습니다. 요컨대 한 사용자가 문제를 _한 번_ 해결하면, 많은 사람이 그 해결책이 정확히 어떻게 동작하는지 알 필요 없이(원한다면 알아볼 수도 있습니다) 그 혜택을 누릴 수 있습니다. --- **Derivation** Published: URL: https://zero-to-nix.com//concepts/derivations *derivation*은 Nix가 Nix 패키지를 [_실체화_][realisation]하는 데 사용하는 명령입니다. derivation은 [Nix 언어](#nix-language)의 특별한 `derivation` 함수를 사용하여 생성됩니다. derivation은 임의 개수의 다른 derivation에 의존할 수 있으며, 하나 이상의 최종 [출력](#outputs)을 생성합니다. derivation과 이를 빌드하는 데 필요한 모든 의존성—직접 의존성, 그리고 그 의존성들의 모든 의존성 등—을 통틀어 [클로저][closure]라고 합니다. ## Derivation 출력 \{#outputs} 가장 일반적인 출력은 다음과 같습니다. - `out`: 가장 범용적인 출력 - `lib`: 라이브러리 출력용 - `dev`: 헤더 파일 같은 일반적인 개발 리소스 - `man`: 매뉴얼 페이지용 derivation과 이를 빌드하는 데 필요한 모든 의존성—직접 의존성, 그리고 그 의존성들의 모든 의존성 등—을 통틀어 *패키지 클로저*라고 합니다. derivation을 Nix 패키지의 _계획_ 또는 *청사진*으로 생각하면 이해하는 데 도움이 될 수 있습니다. ## Nix 언어에서의 derivation \{#nix-language} [Nix 언어][lang]에서 derivation은 [`derivation`][func] 함수를 사용하여 생성됩니다. 다음은 `derivation`의 타입 시그니처를 [Haskell] 풍의 시그니처로 표현한 것입니다.[^1] ```haskell title="Derivation type signature" disableClipboard derivation :: { system : String , name : String , builder : Path | Derivation , ?args : [String] , ?outputs : [String] } -> Derivation ``` 다음은 derivation의 예시입니다. ```nix title="Example derivation" derivation { # A name for the derivation (whatever you choose) name = "hello-text"; # The system realising the derivation system = "x86_64-linux"; # The program realising the derivation builder = "bash"; # Arguments passed to the builder program args = ["-c" "mkdir $out && echo Hello world > $out/hello.txt"] }; ``` 이것이 전부입니다! `derivation` 함수는 이 인수들만 받습니다. 하지만 `args`를 통해 전달하는 스크립트 로직은 얼마든지 복잡해질 수 있으므로, derivation은 훨씬 덜 단순해질 수 있습니다. ### 문자열 보간 Nix가 이 문자열을 보면... ```nix title="my-file.nix" { buildPhase = '' mv ${pkgs.website}/favicon.ico ''; } ``` derivation의 문자열 출력은 항상 [Nix 스토어 경로][store]입니다 ## Derivation 출력 ## 실체화 ### 특수 변수 derivation을 작성할 때 알아 두어야 할 특수 변수가 두 가지 있습니다. - `$out`은 빌드 출력을 위한 디렉터리 구조의 루트를 나타냅니다. - `$src`는 빌드 소스를 나타냅니다. ## 표준 환경 \{#stdenv} Nix 생태계의 derivation 대부분은 [표준 환경][stdenv]의 [`mkDerivation`][mk] 함수를 기반으로 합니다. 원시 `derivation` 함수로 derivation을 만드는 것도 *가능*하지만, 이를 감싸는 래퍼 함수를 사용하는 것이 훨씬 더 일반적입니다. 아마도 가장 흔히 사용되는 래퍼 함수는 [`stdenv.mkDerivation`][mk]일 것입니다. 인수: - 패키지의 `name`입니다. 대신 `pname`과 `version`을 지정하면 `name`은 결국 `${pname}-${version}`이 됩니다. ## 기타 derivation 함수 `stdenv.mkDerivation` 외에도 특정 언어, 프레임워크 등을 위한 맞춤형 derivation 래퍼가 많이 있습니다(그리고 그중 다수는 실제로 `stdenv.mkDerivation`을 감쌉니다). 몇 가지 예시는 다음과 같습니다. - [Go]용 [`buildGoModule`][buildgomodule] - [Rust]용 [`buildRustPackage`][buildrustpackage] - [Python]용 [`buildPythonApplication`][buildpythonapplication] Nix 생태계에서 이 밖에도 훨씬 더 많은 함수를 접하게 될 것입니다. 또한 언제든지 자신만의 derivation 함수를 자유롭게 만들 수 있으며, `buildPythonApplication` 같은 헬퍼 함수를 감쌀 수도 있습니다. [^1]: 이 아이디어를 제공해 주신 [Ian Henry][ian]에게 감사드립니다. [buildgomodule]: https://nixos.org/manual/nixpkgs/stable/#sec-language-go [buildpythonapplication]: https://nixos.org/manual/nixpkgs/stable/#python [buildrustpackage]: https://nixos.org/manual/nixpkgs/stable/#rust [closure]: /concepts/closures [func]: /concepts/derivations [go]: https://go.dev [haskell]: https://www.haskell.org [ian]: https://ianthehenry.com/ [lang]: /concepts/nix-language [mk]: https://nixos.org/manual/nixpkgs/stable/#sec-using-stdenv [python]: https://python.org [realisation]: /concepts/realisation [rust]: https://rust-lang.org [stdenv]: https://nixos.org/manual/nixpkgs/stable/#chap-stdenv [store]: /concepts/nix-store --- **개발 환경** Published: URL: https://zero-to-nix.com//concepts/dev-env Nix *개발 환경*은 셸 시스템 환경을 빌드하는 [derivation]입니다. 이 환경은 호스트로부터 [밀폐][hermetically] 격리되어 있습니다. 따라서 다른 어떤 개발 환경도 이 환경을 변경하거나 그 안의 도구를 재정의할 수 없습니다. 이를 통해 특정 프로젝트의 모든 개발 도구(환경 [클로저][closure])를 하나의 개발 셸에 담을 수 있습니다. 이 개발 셸은 성격이 비슷한 프로젝트(같은 프로그래밍 언어, 같은 의존성 집합 등)의 개발 셸과도 분리되어 있습니다. [hermetically]: /concepts/hermeticity [closure]: /concepts/closures [derivation]: /concepts/derivations --- **생태계** Published: URL: https://zero-to-nix.com//concepts/ecosystem *Nix 생태계*는 [Nix] 패키지 관리자와 [언어][language]를 핵심으로 삼으면서도, Nix 위에 구축된 관련 도구와 시스템의 방대한 네트워크까지 포함하는 소프트웨어 생태계입니다. 공식적인 측면에서 Nix 생태계에는 [NixOS], [NixOps], [Hydra], [Home Manager][hm] 및 [기타 프로젝트][others]가 포함됩니다. 비공식적인 측면에서 Nix 생태계에는 [언어][language] 라이브러리와 헬퍼부터 [패키지 저장소][packages], 개발자 도구, 그리고 그 너머에 이르기까지 모든 것이 포함됩니다. 관점에 따라서는 [GNU Guix][guix]처럼 Nix에서 영감을 받은 프로젝트나, [재현성][reproducibility] 및 [선언형 설정][declarative]과 같은 원칙을 중시하는 Nix의 태도를 공유하는 프로젝트도 Nix 생태계의 범주에 속한다고 볼 수 있습니다. 경계를 어디에 긋든, Nix를 시작하면 소프트웨어 업계의 광대한 영역에 손이 닿게 됩니다. [declarative]: /concepts/declarative [guix]: http://guix.gnu.org [hm]: https://github.com/nix-community/home-manager [hydra]: https://github.com/NixOS/hydra [language]: /concepts/nix-language [nix]: /concepts/nix [nixops]: https://github.com/NixOS/nixops [nixos]: /concepts/nixos [others]: https://github.com/nix-community [packages]: /concepts/packages [reproducibility]: /concepts/reproducibility --- **FlakeHub** Published: URL: https://zero-to-nix.com//concepts/flakehub [FlakeHub]는 [Determinate Systems][detsys]가 만든, [Nix 플레이크][flakes]를 찾아보고 게시하기 위한 플랫폼입니다. FlakeHub는 Nix만으로는 제공하지 않는 다양한 기능을 제공합니다. - `~`(유연한 패치)와 `=`(정확한 일치) 같은 버전 수식어를 포함한 플레이크용 [시맨틱 버저닝][semver] - 다양한 방식으로 Nix 플레이크 생태계를 탐색하는 기능: - 일반 텍스트 검색 - [모든 플레이크][all-flakes] - [모든 조직][all-orgs] - [`nixos`][label-nixos]나 [`rust`][label-rust] 같은 레이블을 통한 탐색 - GitHub Actions를 이용한 자동화된 플레이크 [게시][publishing]. 프로젝트의 Actions 설정을 구성하도록 도와주는 사용하기 쉬운 [마법사][wizard]도 제공합니다. FlakeHub는 FlakeHub API를 대상으로 다양한 작업을 수행하는 데 사용할 수 있는 [`fh`][fh]라는 CLI 도구도 제공합니다. 저희 [Determinate Systems][detsys]는 FlakeHub가 [Nix 플레이크][flakes] 사용의 중요한 측면을 더 간단하고—그리고 재미있게!—만들어 준다고 믿지만, FlakeHub는 독점 플랫폼이며 대부분 오픈 소스가 아닙니다. [시맨틱 버저닝][semver]과 [공개 플레이크][visibility] 게시를 포함하여 FlakeHub 기능의 대부분은 무료입니다. 다시 말해, [GitHub]를 사용하지 않고도 [Git]을 사용할 수 있는 것처럼 FlakeHub를 사용하지 않고도 [Nix]와 [Nix 플레이크][flakes]를 사용할 수 있습니다. [all-flakes]: https://flakehub.com/flakes [all-orgs]: https://flakehub.com/orgs [detsys]: https://determinate.systems [fh]: https://github.com/DeterminateSystems/fh [flakehub]: https://flakehub.com [flakes]: /concepts/flakes [git]: https://git-scm.com [github]: https://github.com [label-nixos]: https://flakehub.com/label/nixos [label-rust]: https://flakehub.com/label/rust [nix]: /concepts/nix [publishing]: https://determinate.systems/posts/introducing-flakehub#publish [semver]: https://docs.determinate.systems/flakehub/concepts/semver [visibility]: https://docs.determinate.systems/flakehub/concepts/visibility [wizard]: https://flakehub.com/new --- **Nix 플레이크** Published: URL: https://zero-to-nix.com//concepts/flakes [업스트림 Nix 프로젝트][upstream]에서 플레이크는 **여전히 실험적 기능으로 간주**되며, 현재로서는 안정 기능으로 선언할 구체적인 일정이 없습니다. 이 때문에 업스트림 Nix를 사용한다면 플레이크를 명시적으로 [활성화][enable-flakes]해야만 사용할 수 있습니다. [빠른 시작][quick-start]의 첫 부분에서 설치하는 [Determinate Systems][detsys]의 다운스트림 Nix 배포판인 [Determinate Nix][det-nix]에서는 플레이크가 [**안정 기능으로 간주**][stable-flakes]되므로 별도 설정 없이 바로 사용할 수 있습니다. 업스트림 Nix와 Determinate Nix 중 무엇을 선택하든, 이미 Nix 사용자라면 플레이크 사용법을 익히고, 이제 막 [시작하는][quick-start] 단계라면 플레이크로 Nix 여정을 시작하실 것을 강력히 권장합니다. Nix *플레이크*는 루트에 `flake.nix`와 [`flake.lock`](#lockfile)이 있는 디렉터리로, 다른 사람들이 [패키지 빌드][packages], [프로그램 실행][run], [개발 환경][env] 사용, [NixOS] 시스템 구축 등에 활용할 수 있는 Nix 표현식을 [출력](#outputs)합니다. 필요한 경우 플레이크는 다른 플레이크의 출력을 [입력](#inputs)으로 사용할 수 있습니다. 플레이크를 [Nix 코드][lang]의 처리기로 생각하면 이해하는 데 도움이 될 수 있습니다. 플레이크는 Nix 표현식을 [입력](#inputs)으로 받아 [패키지 정의][packages], [개발 환경][env], [NixOS] 설정처럼 Nix가 사용할 수 있는 것을 [출력](#outputs)합니다. 따라서 플레이크는 일종의 사슬을 형성합니다. 예를 들어, 제가 [Nixpkgs]—이것 역시 플레이크입니다!—가 출력하는 헬퍼 함수를 사용해 패키지 빌드를 정의하는 플레이크를 만든다고 가정해 봅시다. 그러면 제 팀원은 제 플레이크의 패키지 정의를 Nix 개발 환경의 일부로 사용할 수 있습니다. 그다음 다른 팀은 그 개발 환경을 자신들의 프로젝트 중 하나에서 사용할 수 있습니다. 이런 식으로 계속 이어집니다. ## 플레이크 참조 \{#references} *플레이크 참조*는 플레이크가 위치한 곳을 나타내는 문자열 표현입니다. 플레이크 참조는 다음 두 곳에서 사용됩니다. 1. 플레이크의 출력에 의존하기 위한 플레이크 [입력 선언](#inputs)에서 사용됩니다. 1. 셸 환경에서 `nix run github:DeterminateSystems/flake-checker`와 같은 명령을 실행할 때 플레이크 참조를 사용합니다(이 명령은 [flake-checker] 프로그램을 실행합니다). 다음은 플레이크 참조의 몇 가지 예시입니다. 참조 | 설명 :---------|:----------- `path:/home/nix-stuff/my-flake` | 현재 호스트의 `/home/nix-stuff/my-flake` 디렉터리 `github:DeterminateSystems/zero-to-nix` | [DeterminateSystems/zero-to-nix][gh-z2n] GitHub 저장소 `github:DeterminateSystems/zero-to-nix/other` | [DeterminateSystems/zero-to-nix][gh-z2n] GitHub 저장소의 [`other`][other] 브랜치 `github:DeterminateSystems/zero-to-nix/d51c83a5d206e882a6f15a282e32b7079f5b6d76` | [DeterminateSystems/zero-to-nix][gh-z2n] GitHub 저장소의 커밋 [`d51c83a5d206e882a6f15a282e32b7079f5b6d76`][hash] `github:DeterminateSystems/zero-to-nix/pull/2/head` | [DeterminateSystems/zero-to-nix][gh-z2n] GitHub 저장소의 풀 리퀘스트 1 `nixpkgs` | [Nixpkgs]의 [`nixpkgs-unstable`][unstable] 브랜치의 최신 리비전(`github:NixOS/nixpkgs`의 별칭) `nixpkgs/release-22.11` | Nixpkgs의 [`release-22.11`][22-11] 브랜치 [`https://flakehub.com/f/NixOS/nixpkgs/0.2405.*`][fh-nixpkgs] | [FlakeHub]에 호스팅된 [Nixpkgs]의 [`nixos-24.05`][branch] 브랜치의 최신 리비전 플레이크 참조에 대한 더 체계적인 설명은 [공식 문서][refs-official]에서 확인할 수 있습니다. ### 참조와 리비전 \{#revisions} 플레이크 참조는 _항상_ 플레이크의 특정 리비전을 가리킵니다. 예를 들어 [Nixpkgs]는 하나의 플레이크이지만, 수천 개에 이르는 Nixpkgs의 각 리비전마다 플레이크 참조가 있습니다. ## 플레이크 입력 \{#inputs} *플레이크 입력*은 플레이크를 빌드하는 데 필요한 Nix 의존성입니다. 집합의 각 입력은 GitHub, 일반 Git 저장소, 심지어 여러분의 파일 시스템 등 다양한 소스에서 가져올 수 있습니다. 또한 입력은 서로의 입력을 수정할 수 있으므로, 예를 들어 여러 의존성이 모두 같은 버전의 nixpkgs에 의존하도록 보장할 수 있습니다. 이는 `inputs..follows` 속성을 통해 이루어집니다. ```nix title="flake.nix" { inputs.nixpkgs.url = "github:NixOS/nixpkgs"; } ``` 플레이크 입력 스키마에 대한 전체 설명은 [Nix 매뉴얼][manual]에서 확인할 수 있습니다. ### `flake.lock` 파일 \{#lockfile} 모든 플레이크 입력은 `flake.lock`이라는 잠금 파일에서 특정 [리비전](#revisions)으로 [고정][pinning]됩니다. 이 파일은 리비전 정보를 [JSON] 형식으로 저장합니다. `flake.lock` 파일은 Nix 플레이크가 순수하게 결정론적인 출력을 갖도록 보장합니다. `flake.lock` 없이 `flake.nix` 파일만 있다면 불완전한 것, 즉 일종의 원형 플레이크(proto-flake)로 간주해야 합니다. `nix build`, `nix develop`, 심지어 `nix flake show`처럼 플레이크를 대상으로 실행하는 모든 Nix CLI 명령은 `flake.lock`을 자동으로 생성합니다. 다음은 [Nixpkgs]를 특정 리비전으로 고정하는 `flake.lock` 파일의 예시 부분입니다: ```json title="flake.lock" { "nodes": { "nixpkgs": { "locked": { "lastModified": 1668703332, // A SHA of the contents of the flake "narHash": "sha256-PW3vz3ODXaInogvp2IQyDG9lnwmGlf07A6OEeA1Q7sM=", // The GitHub org "owner": "NixOS", // The GitHub repo "repo": "nixpkgs", // The specific revision "rev": "de60d387a0e5737375ee61848872b1c8353f945e", // The type of input "type": "github" } } // Other inputs } } ``` 이 `flake.lock`이 다음과 같은 [입력 블록](#inputs)을 가진 `flake.nix`와 함께 있다면... ```nix title="flake.nix" { inputs.nixpkgs.url = "nixpkgs"; outputs = { self, nixpkgs }: { # Define outputs here }; } ``` ...`nixpkgs` 속성은 암묵적으로 `de60d387a0e5737375ee61848872b1c8353f945e` 리비전에 고정됩니다. 해당 리비전 정보가 Nix 코드 자체에는 없더라도 마찬가지입니다. ### 플레이크 레지스트리 \{#registries} [_플레이크 레지스트리_][registry-official]는 전체 플레이크 참조 대신 기호 식별자를 사용하여 플레이크를 참조할 수 있게 해 주는 편의 기능입니다. 가장 널리 사용되는 기호 식별자는 `nixpkgs`이며, 이는 `github:NixOS/nixpkgs/nixpkgs-unstable` 플레이크 [참조](#references)의 별칭입니다 여러분이 접할 수 있는 몇 가지 기호 식별자는 다음과 같습니다: | 기호 식별자 | 전체 플레이크 참조 | | :--------------------------- | :-------------------------------------- | | [`nixpkgs`][nixpkgs] | `github:NixOS/nixpkgs/nixpkgs-unstable` | | [`flake-utils`][flake-utils] | `github:numtide/flake-utils` | | [`home-manager`][hm] | `github:nix-community/home-manager` | 기본 전역 플레이크 레지스트리 전체는 [JSON 파일][registry-json]로 관리됩니다. 다음은 기호 식별자를 사용하는 플레이크의 예시입니다: ```nix title="flake.nix" { outputs = { self, nixpkgs, flake-utils }: let pkgs = import nixpkgs { inherit system; }; in flake-utils.lib.eachDefaultSystem (system: { devShells.default = pkgs.mkShell { packages = with pkgs; [ curl git jq wget ]; }; }); } ``` 이 플레이크에서는 [`inputs` 블록](#inputs)이 생략되었다는 점에 유의하십시오. 플레이크 레지스트리 사용은 언제나 선택 사항입니다. ## 플레이크 출력 \{#outputs} *플레이크 출력*은 플레이크가 빌드 과정에서 만들어 내는 결과물입니다. 각 플레이크는 여러 종류의 출력을 동시에 가질 수 있으며, 그 예는 다음과 같습니다(이에 국한되지 않습니다): - [Nix 패키지][packages] - [Nix 개발 환경][env] - [NixOS] 설정 - [Nix 템플릿](#templates) 플레이크 출력은 함수로 정의되며, 이 함수는 해당 플레이크의 각 입력([입력](#inputs) 섹션에서 정한 식별자를 이름으로 사용)을 담은 속성 집합을 입력으로 받습니다. ### 함수 내보내기 \{#functions} 플레이크는 패키지나 NixOS 설정 같은 것 외에도 다른 곳에서 사용할 Nix [함수][functions]를 출력할 수도 있습니다. 예를 들어 [Nixpkgs]는 `lib` 속성을 통해 많은 헬퍼 함수를 출력합니다. `lib`를 사용해 함수를 출력하는 관례는 Nixpkgs뿐 아니라 다른 많은 Nix 프로젝트에서도 따르고 있습니다. 하지만 원하는 어떤 속성을 통해서든 자유롭게 함수를 출력할 수 있습니다. 다음은 `lib` 속성을 통해 `sayHello` 함수를 출력하는 플레이크 예시입니다. 이 함수는 이름을 입력으로 받아 그 이름을 가진 사람에게 인사하는 문자열을 출력합니다: ```nix title="flake.nix" { outputs = { self }: { lib = { sayHello = name: "Hello there, ${name}!"; }; }; } ``` 그러면 다른 Nix 플레이크가 이 플레이크를 [입력](#inputs)으로 지정하고 `sayHello`를 어떤 목적으로든 사용할 수 있습니다. ### 시스템 특정성 [패키지][packages], [개발 환경][env], [NixOS] 설정을 비롯한 일부 플레이크 출력은 [시스템별로 지정][specificity]되어야 합니다. 다음은 `x86_64-linux` 시스템(64비트 AMD/Intel Linux)에서 사용할 수 있는 패키지를 출력하는 플레이크 예시입니다: ```nix title="flake.nix" { outputs = { self, nixpkgs }: let # Declare the system system = "x86_64-linux"; # Use a system-specific version of Nixpkgs pkgs = import nixpkgs { inherit system; }; in { # Output `ponysay` as the default package of the flake packages.${system}.default = pkgs.ponysay; }; } ``` 하지만 많은 경우 [패키지][packages]나 [개발 환경][env] 같은 것을 여러 시스템용으로 출력해야 합니다. [`flake-utils`][flake-utils] 같은 헬퍼 라이브러리는 이를 위한 편리한 방법을 제공합니다. 다음과 같이 Nix 함수를 사용할 수도 있습니다: ```nix title="flake.nix" { outputs = { self, nixpkgs }: let # The set of systems to provide outputs for allSystems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ]; # A function that provides a system-specific Nixpkgs for the desired systems forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f { pkgs = import nixpkgs { inherit system; }; }); in { packages = forAllSystems ({ pkgs }: { default = { # Package definition }; }); }; } ``` ## 플레이크 템플릿 \{#templates} [_플레이크 템플릿_][init]을 사용하면 미리 제공된 내용으로 새 Nix 프로젝트를 초기화하거나 기존 프로젝트에 파일 묶음을 추가할 수 있습니다. [`nix flake init`][init] 명령으로 플레이크 템플릿을 초기화할 수 있습니다. 플레이크는 `templates` 속성을 사용하여 템플릿을 [출력](#outputs)할 수 있습니다. 다음은 예시입니다: ```nix title="flake.nix" { outputs = { self }: { templates = { starter-template = { path = ./my-starter-template; description = "A getting started template for a new Nix project"; }; }; }; } ``` 이 템플릿 정의에 대해 `nix flake init --template `를 실행하면 Nix는 `./my-starter-template` 디렉터리의 내용을 현재 디렉터리로 복사합니다(기존 파일은 덮어쓰지 않습니다). [22-11]: https://github.com/nixOS/nixpkgs/tree/release-22.11 [branch]: https://github.com/nixos/nixpkgs/tree/nixos-24.05 [det-nix]: https://docs.determinate.systems/determinate-nix [detsys]: https://determinate.systems [enable-flakes]: https://wiki.nixos.org/wiki/Flakes#Setup [env]: /concepts/dev-env [fh-nixpkgs]: https://flakehub.com/flake/NixOS/nixpkgs [flake-checker]: https://github.com/DeterminateSystems/flake-checker [flake-utils]: https://github.com/numtide/flake-utils [flakehub]: https://flakehub.com [functions]: /concepts/nix-language [gh-z2n]: https://github.com/DeterminateSystems/zero-to-nix [hash]: https://github.com/DeterminateSystems/zero-to-nix/tree/d51c83a5d206e882a6f15a282e32b7079f5b6d76 [hm]: https://github.com/nix-community/home-manager [init]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake-init [json]: https://json.org [lang]: /concepts/nix-language [manual]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake#flake-inputs [nixos]: /concepts/nixos [nixpkgs]: /concepts/nixpkgs [other]: https://github.com/DeterminateSystems/zero-to-nix/tree/other [packages]: /concepts/packages [pinning]: /concepts/pinning [refs-official]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-flake#flake-references [registry-json]: https://github.com/NixOS/flake-registry/blob/master/flake-registry.json [registry-official]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-registry [quick-start]: /start [run]: /start/nix-run [specificity]: /concepts/system-specificity [stable-flakes]: https://determinate.systems/blog/determinate-nix-30 [unstable]: https://github.com/NixOS/nixpkgs/tree/nixpkgs-unstable [upstream]: https://github.com/NixOS/nix --- **밀폐성** Published: URL: https://zero-to-nix.com//concepts/hermeticity *밀폐성*은 Nix 빌드의 속성으로, 다양한 메커니즘을 통해 빌드를 호스트 시스템으로부터 격리합니다. 그 결과 호스트의 변경 사항이 빌드에 영향을 줄 수 없으므로, 동일한 소스 입력 집합이 항상 동일한 빌드 출력에 대응하는 시스템이 됩니다. 밀폐되지 않은 시스템은 모두 "비순수(impure)" 시스템이라고 하며, 이는 입력 집합 외부의 변경 사항이 빌드 결과에 영향을 줄 수 있음을 뜻합니다. 이는 Nix의 "순수성" 속성과 반대되는 개념입니다. --- **증분 빌드** Published: URL: https://zero-to-nix.com//concepts/incremental-builds *증분 빌드*는 지능적인 [캐싱][caching]과 같은 메커니즘을 사용하여 이미 사용할 수 있는 산출물을 다시 빌드하지 않으므로, 소프트웨어 산출물의 전체 의존성 트리를 매번 빌드할 필요가 없는 빌드 과정입니다. Nix는 증분 빌드를 제공하는 여러 빌드 시스템 가운데 하나입니다. ## Nix가 증분 빌드를 제공하는 방식 \{#how} Nix는 모든 빌드 결과를 [Nix 스토어][store]에 저장함으로써 [Nix 패키지][packages]에 대한 증분 빌드를 제공하는 여러 빌드 시스템 가운데 하나입니다. Nix는 [패키지][packages]를 빌드할 때마다 해당 패키지의 전체 [클로저][closure], 즉 의존성 트리를 빌드합니다. 해시 부분 덕분에 Nix는 무엇을 빌드할 필요가 없는지 "알" 수 있습니다. `final-production-artifact` 패키지를 빌드하는 데 `super-important-dependency` 패키지가 필요하다면, Nix는 `super-important-dependency`의 [derivation]을 검사하여 해당 의존성의 해시를 계산하고, 이를 통해 다음과 같은 Nix 스토어 경로를 계산할 수 있습니다. 이 정보를 바탕으로 Nix는 다음 위치 중 한 곳에 해당 산출물이 이미 있는지 확인할 수 있습니다. - 로컬 [Nix 스토어][store] - 설정된 [바이너리 캐시][binary] 중 하나(있는 경우) Nix는 이 위치들 중 어디에서도 실체화된 산출물을 찾지 못한 경우에만 해당 derivation을 빌드합니다. 이는 큰 [클로저][closure]를 빌드할 때 엄청난 차이를 만들 수 있습니다. ## Nix에서 증분 빌드가 가져오는 효과 \{#consequences} [패키지][Packages]는 여러 면에서 Nix의 핵심 구성 산출물입니다. [Nix 개발 환경][env]은 패키지를 밀폐된 방식으로 제공하고, [NixOS]는 Nix 패키지를 기반으로 구축되는 식입니다. 이는 Nix의 증분 빌드 덕분에 Nix와 관련된 거의 모든 것이 훨씬 빨라지고 리소스도 덜 사용하게 된다는 뜻입니다. [binary]: /concepts/caching#binary-caches [caching]: /concepts/caching [closure]: /concepts/closures [derivation]: /concepts/derivations [env]: /concepts/dev-env [nixos]: /concepts/nixos [packages]: /concepts/packages [store]: /concepts/nix-store --- **Nix** Published: URL: https://zero-to-nix.com//concepts/nix [*Nix*][nix]는 여러 가지를 가리키기 때문에 다소 헷갈릴 수 있는 용어입니다: 1. 순수 함수형 [프로그래밍 언어][lang] 2. [Nix CLI](#cli) 3. Nix [패키지 관리 시스템][package-management] 전반 이들은 모두 서로 밀접하게 연관되어 있으므로 하나의 도구로 생각해야 합니다. 이 문서에서는 Nix의 이 세 가지 측면을 각각 살펴보겠습니다. Nix 프로젝트는 완전한 오픈 소스이며, 주로 [GitHub]의 [`NixOS`][nixos-org] 조직에서 개발됩니다. [LGPL 2.1][license] 라이선스를 따르며, 이 라이선스는 일반적으로 상업적 사용에 상당히 관대합니다. 저희 Determinate Systems는 수많은 재능 있는 개인들과 함께 오픈 소스 프로젝트인 Nix에 적극적으로 기여해 왔으며, Nix를 더 좋게 만들겠다는 [사명][mission]의 일환으로 앞으로도 계속 기여할 것입니다. 또한 저희는 기업용 Nix 다운스트림 배포판인 [Determinate Nix][det-nix]도 만들었습니다. ## Nix CLI \{#cli} 현재 두 가지 Nix CLI가 사용되고 있습니다: - [통합 Nix CLI](#unified-cli)는 현재 실험 단계이지만, [Determinate Systems][ds]는 Nix를 사용할 때 이 CLI를 권장합니다. 모든 Nix 기능을 하나의 `nix` 실행 파일에 담았으며 [플레이크][flakes]를 지원합니다 - [기존 Nix CLI](#original-cli)는 현재 표준이지만, [Determinate Systems][ds]는 Nix를 사용할 때 이 CLI를 권장하지 _않습니다_. ### 통합 CLI \{#unified-cli} *통합 CLI*는 `nix`라는 실행 파일 하나만 사용하는, 아직 실험 단계인 Nix 사용 방식입니다. 기존 `nix-build` 도구 대신 [패키지][packages]를 빌드하는 `nix build`, 기존 `nix-shell` 도구 대신 Nix [개발 환경][env]을 활성화하는 `nix develop`, 기존 `nix-store` 도구 대신 [Nix 스토어][store]를 관리하는 `nix store` 등의 명령어를 비롯해 _모든_ Nix 기능이 이 도구 하나에 담겨 있습니다. 통합 CLI는 아직 공식 CLI가 아니므로, Nix 설정의 `experimental-features` 목록에 `nix-command`를 추가하여 명시적으로 활성화해야 합니다. [Determinate Nix Installer][install]가 통합 CLI를 설치하고 Nix 설정에서 활성화까지 해 주므로, 여기서는 통합 CLI 설정 방법을 다루지 않습니다. ### 기존 CLI \{#original-cli} Nix의 *기존 CLI*는 여전히 공식 CLI이지만, 앞서 언급했듯이 다음 두 가지 이유로 Nix를 처음 사용하는 분에게는 권장하지 않습니다: 1. 플레이크가 등장하기 전에 만들어졌기 때문에 [Nix 플레이크][flakes]와 호환되지 않습니다. 1. [패키지][packages]를 빌드하는 `nix-build`, Nix [개발 환경][env]을 위한 `nix-shell`, [Nix 스토어][store]를 관리하는 `nix-store` 등 여러 가지 CLI 도구를 익혀야 하므로, [통합 CLI](#unified-cli)에 비해 인지적 부담이 상당히 큽니다. [Determinate Nix Installer][install]는 기본적으로 [통합 CLI](#unified-cli)를 활성화하지만, 기존 CLI의 도구도 계속 사용할 수 있도록 남겨 둡니다. [det-nix]: https://docs.determinate.systems/determinate-nix [ds]: https://determinate.systems [env]: /concepts/dev-env [flakes]: /concepts/flakes [github]: https://github.com [install]: /concepts/nix-installer [lang]: /concepts/nix-language [license]: https://github.com/nixOS/nix?tab=LGPL-2.1-1-ov-file [mission]: https://determinate.systems/posts/we-want-to-make-nix-better [nix]: https://nixos.org [nixos-org]: https://github.com/NixOS [packages]: /concepts/packages [package-management]: /concepts/package-management [store]: /concepts/nix-store --- **Determinate Nix Installer** Published: URL: https://zero-to-nix.com//concepts/nix-installer [Determinate Nix Installer][install]는 [Determinate Systems][ds]가 만든 빠르고 안정적인 Nix 설치 프로그램입니다. 현재 Linux와 macOS를 모두 지원합니다. {/* */} ## Determinate Nix Installer 사용하기 \{#using} 다음 명령어로 시스템에서 설치 프로그램을 실행할 수 있습니다: ```shell title="One command to install Nix" curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install ``` 더 자세한 안내는 Zero to Nix의 [시스템에서 Nix 실행하기][start]를 참고하십시오. [ds]: https://determinate.systems [install]: https://github.com/DeterminateSystems/nix-installer [start]: /start/install --- **Nix 언어** Published: URL: https://zero-to-nix.com//concepts/nix-language Nix는 Nix *패키징 시스템*을 구동하는 *프로그래밍 언어*입니다. ## 왜 프로그래밍 언어입니까? Nix에 도대체 왜 프로그래밍 언어가 _필요한지_ 궁금하실 수 있습니다. 왜 패키지를 JSON, YAML, TOML 같은 스키마로 선언할 수는 없습니까? 그 방식의 문제는 Nix가 패키지를 설정하고 서로 조합할 수 있게 하는 방식이 동적이라는 데 있습니다. *프로그래밍 언어*로서의 Nix는 일종의 "함수가 있는 JSON"이라고 생각할 수 있습니다. 모든 구문은 [선언형][declarative]입니다. 즉, Nix 패키지를 구성하는 순차적인 명령 흐름이 없습니다. 그 대신 *속성 집합*의 필드에 값을 할당하는 함수가 호출되며, 이 값은 다시 다른 값에 할당될 수 있습니다. ## Nix는 어떻게 동작합니까? Nix는 프로그래밍 언어 설계의 몇 가지 중요한 특성을 활용하여 동작합니다. 이 용어들이 무엇을 의미하고 서로 어떻게 맞물려 동작하는지 아직 익숙하지 않다면, 일부 용어는 어렵게 느껴질 수 있습니다. 그러니 먼저 다음 원칙들을 살펴봅시다. *Nix*는 순수하고, 함수형이며, 지연 평가되고, 선언형이며, 재현 가능한 프로그래밍 언어입니다. | 개념 | 설명 | | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | 순수 | 함수가 *부수 효과*를 일으킬 수 없도록 하는 프로그래밍 언어 설계 개념입니다. 유일한 결과는 함수가 반환하는 값입니다 | | 함수형 | *함수*를 함수 인자로 전달하거나 결과로 반환할 수 있도록 하는 프로그래밍 언어 설계 개념입니다 | | 지연 평가 | 함수와 데이터 컬렉션이 계산을 완료하는 데 필요해질 때까지 평가되지 않도록 하는 프로그래밍 언어 설계 개념입니다 | | 선언형 | 결과를 _어떻게_ 달성할지 컴퓨터에 지시하는 대신, 시스템의 결과를 기술하는 것입니다 | | [재현 가능](/zero-to-nix/concepts/reproducibility) | 두 번 수행한 작업이 같은 결과를 냅니다. 같은 입력은 같은 출력에 대응합니다 | ## 구문 기초 앞서 언급했듯이 Nix는 *할당*을 사용하여 패키지, 모듈 및 기타 유틸리티를 위한 데이터를 계산하고 처리합니다. 예를 들어 아래 코드는 `my_function`이라는 함수를 매개변수 `2`와 `3`으로 호출하고, 그 출력을 `my_value` 필드에 할당합니다. ```nix title="Assignments" { my_value = my_function 2 3; } ``` 함수는 다음 구문으로 정의하며, 여기서 `x`와 `y`는 함수에 전달되는 속성입니다: ```nix title="Functions" { my_function = x: y: x + y; } ``` 함수 본문은 함수의 결과를 자동으로 반환합니다. 위 예제에서 볼 수 있듯이, 함수는 함수와 매개변수 사이를 공백으로 구분하여 호출합니다. 매개변수를 구분하는 데 쉼표는 필요하지 않습니다. 가장 흔히 쓰이는 두 가지 데이터 구조는 *속성 집합*과 *리스트*입니다. 속성 집합은 키-값 저장소입니다. 리스트는 서로 다른 타입의 값을 담을 수 있으며, 쉼표로 구분할 필요가 없습니다. ```nix title="Recursive attributes" rec { number_key = 5; list_key = [ number_key true "Hello" ]; } ``` `rec` 키워드를 사용하면 속성 집합이 자기 자신을 참조할 수 있습니다. 구문에 대한 더 자세한 설명은 [Nix 언어](https://nixos.org/manual/nix/stable/language) 매뉴얼 섹션을 확인하십시오. ## Derivation \{#derivations} Nix를 다른 프로그래밍 언어와 구별 짓고 단순한 설정 언어 이상의 것으로 만들어 주는 요소는 바로 `derivation` 함수입니다. 이는 패키지의 빌드 과정을 정의하는 데 사용하는 내장 함수입니다. 자세한 내용은 [derivation][derivations] 개념 문서를 참조하십시오. [declarative]: /concepts/declarative [derivations]: /concepts/derivations --- **Nix 스토어** Published: URL: https://zero-to-nix.com//concepts/nix-store *Nix 스토어*는 파일 시스템 안에 있는 저장 시스템으로, 기본적으로 `/nix/store`를 루트로 합니다. Nix 데몬은 Nix 스토어에 여러 가지를 저장합니다: - [Derivation][Derivations]: `/nix/store/-my-package.drv`처럼 `.drv` 접미사가 붙은 독립 파일입니다 - [derivation][derivations]의 결과물: `/nix/store/-my-package/`처럼 빌드 출력을 담고 있는 폴더입니다 - [패치][Patches]: `/nix/store/-my-package.patch`처럼 `.patch` 접미사가 붙은 독립 파일입니다 ## 스토어 경로 \{#store-paths} Nix 스토어의 경로는 다음과 같은 구조를 가집니다: 스토어 경로를 구성 요소별로 나누어 살펴봅시다: 1. **루트 경로**는 기본적으로 `/nix/store`입니다. 2. **입력 해시**는 패키지를 빌드하는 데 사용된 [derivation][derivations]의 입력으로부터 도출됩니다 3. **패키지 이름**은 패키지 작성자가 지정합니다 Nix의 스토어 경로에 대해 알아 두어야 할 몇 가지 중요한 사항은 다음과 같습니다: - `/nix/store`에 있는 루트 경로는 `/usr/bin` 같은 다른 표준 시스템 경로와 충돌하지 않습니다. - 해시 덕분에 이름이 같은 두 패키지라도 패키지의 입력이 _조금이라도_ 다르면 완전히 다른 경로를 갖게 됩니다. 예를 들어 `my-package-1.0`의 입력에 있는 파일 하나에서 글자 하나만 바꾸더라도 `/nix/store/1aq3wchnvv7yn0d6y1r3j129hjqmv2k3-my-package-1.0` 같은 스토어 경로가 만들어질 수 있습니다. - 패키지 이름은 근본적으로 임의적입니다. 원하는 명명 규칙을 자유롭게 사용할 수 있습니다. 패키지에 버전 개념을 두고 싶지 않다면 이름을 `my-package`로 지정하고 입력 해시로 구분할 수 있습니다. [derivations]: /concepts/derivations [patches]: https://nixos.org/manual/nixpkgs/stable/#sec-patches --- **NixOS** Published: URL: https://zero-to-nix.com//concepts/nixos *NixOS*는 [Nix]를 기반으로 하는 [Linux] 배포판입니다. NixOS는 [Nix 언어][lang]를 사용해 [`configuration.nix` 파일](#configuration)에서 운영체제를 [선언형으로 설정][declarative]할 수 있다는 점에서 여러 배포판 가운데 독보적입니다. 그리고 이러한 설정 가능성은 상당히 깊은 곳까지 미쳐서, 시스템의 [부트 로더][boot], [파일 시스템][filesystem], [윈도우 관리자][window], [커널 모듈][kernel], [OpenSSH] 같은 서비스를 비롯해 훨씬 더 많은 것을 포함합니다. NixOS는 근본적으로 [설정 가능한](#configuration) 배포판일 뿐만 아니라, Nix 덕분에 [원자적 시스템 업데이트](#atomicity), [시스템 롤백](#rollbacks), 견고한 [다중 사용자 지원](#multi-user) 등 다양한 고유 [기능](#features)도 제공합니다. ## Nix의 역할 \{#nix} NixOS 시스템의 모든 것은 [Nix 언어][lang]와 NixOS [모듈 시스템](#modules)을 사용해 설정됩니다. 그때그때 임시방편으로 [패키지][packages]를 설치하고 시스템을 구성하는 대신, 네트워킹 스택, 파일 시스템, 사용자 등 원하는 구체적인 시스템을 [선언][declarative]할 수 있으며, 그러면 Nix가 필요한 모든 [패키지][packages]를 설치하고, 필요한 설정 파일을 제공하고, 선언된 그 밖의 변경 사항을 적용하면서 시스템을 처음부터 빌드해 줍니다. ## 기능 \{#features} NixOS는 [APT], [dpkg] 또는 그 밖의 Linux용 선택지 대신 [Nix]를 [패키지 관리자][pkg]로 사용합니다. Nix 덕분에 NixOS는 다양한 고유 기능을 제공할 수 있습니다. ### 세대 다른 Linux 배포판과 달리, NixOS 시스템 상태에 대한 업데이트는 번호가 붙은 원자적 *세대*를 이룹니다. 원하는 [시스템 설정](#configuration)을 적용하기 위해 `nixos-rebuild switch`를 실행할 때마다 Nix는 세대 번호를 하나씩 늘립니다. 세대의 핵심 이점 중 하나는 시스템 상태의 [원자적 버전](#atomicity) 사이를 자유롭게 전환할 수 있다는 점입니다. ### 원자적 시스템 업데이트 \{#atomicity} NixOS [설정](#configuration)을 변경할 때마다 [`nixos-rebuild switch`][rebuild]를 실행하여 그 설정을 적용할 수 있습니다. 그렇게 하면 NixOS는 시스템 설정에 따라 설치하거나 업그레이드해야 하는 모든 [패키지][packages]를 설치하거나 업그레이드합니다. 그리고 Nix에서 늘 그렇듯이, 각 패키지는 처음부터 [실체화][realised]되어 [파일 시스템 계층 구조 표준(Filesystem Hierarchy Standard)][fhs]을 사용하는 시스템처럼 `/bin`이나 `/usr/bin` 같은 디렉터리에 저장되는 것이 아니라 [Nix 스토어][store]에 저장됩니다. ### 롤백 \{#rollbacks} [시스템 업데이트](#atomicity)와 마찬가지로, NixOS에서는 `nixos-rebuild switch --rollback`을 사용해 시스템을 이전 세대로 롤백할 수 있습니다. 롤백은 완전히 [원자적](#atomicity)이며 [패키지][packages], 시스템 설정, 그리고 NixOS 설정에 지정된 그 밖의 모든 것을 포함합니다. ### 다중 사용자 지원 \{#multi-user} NixOS는 [파일 시스템 계층 구조 표준(Filesystem Hierarchy Standard)][fhs]을 따르지 않고, [패키지][packages]뿐만 아니라 [derivation][derivations]과 기타 산출물을 포함한 모든 것에 [Nix 스토어][store]를 사용합니다. 이를 통해 NixOS는 사용자 *프로필*을 개수 제한 없이 우아한 방식으로 지원할 수 있습니다. 예를 들어 같은 NixOS 호스트의 서로 다른 두 사용자가 서로 다른 버전의 [Git]을 사용할 수 있는데, 이는 `/usr/bin/git` 같은 위치에 있는 전역 `git`을 공유하는 대신 두 사용자가 각각 Nix 스토어 경로의 `git` 실행 파일을 사용할 수 있기 때문입니다: - `/nix/store/sglc12hc6pc68w5ppn2k56n6jcpaci16-git-2.38.1/bin/git` - `/nix/store/8nwsswymka208dpmsy09aydgffvg4bbi-git-2.38.0/bin/git` 다음은 위의 첫 번째 경로를 나타낸 다이어그램입니다: 스토어 경로를 구성 요소별로 나누어 살펴봅시다: 1. **루트 경로**는 기본적으로 `/nix/store`입니다. 2. **해시**는 패키지를 빌드하는 데 사용된 [derivation][derivations]에서 파생됩니다. 3. **패키지 이름**은 패키지 제작자가 지정하는 임의의 슬러그입니다. ## 설정 \{#configuration} 대부분의 Linux 배포판에서는 셸 스크립트와 [`apt-get install`][apt] 같은 임시방편적인 명령을 사용하여 원하는 시스템을 절차적으로 구성합니다. 이와 달리 NixOS에서는 [Nix 언어][lang]를 사용하여 원하는 시스템을 정의할 수 있습니다. 기본적으로 이 정의는 `/etc/nixos`에 저장된 `configuration.nix` 파일에 들어 있습니다. 다음은 설정 예시입니다: ```nix title="/etc/nixos/configuration.nix" { pkgs, ... }: # A pinned version of Nixpkgs passed to the configuration by Nix { # Enable Nix flakes and the unified Nix CLI nix.settings = { experimental-features = "nix-command flakes"; }; # Networking configuration networking.hostName = "justme-dev-box"; # Enable OpenSSH services.openssh.enable = true; # Root filesystem fileSystems."/" = { device = "/dev/sda1"; fsType = "ext4"; }; # Create a user users.users.justme = { isNormalUser = true; initialPassword = "changemeplz"; }; # CLI tools, language runtimes, shells, and other desired packages environment.systemPackages = with pkgs; [ curl jq wget git python openssl zsh ]; } ``` 다음 명령은 위 설정을 적용합니다: ```shell title="Rebuild your NixOS system" nixos-rebuild switch ``` 복잡한 셸 스크립트도, 일련의 설치 명령이나 빌드 명령도 필요 없습니다. 명령 하나만으로 지정한 사양에 따라 시스템 전체를 빌드합니다. ### 모듈 \{#modules} *모듈*은 설정을 만들어 내도록 구성할 수 있는 Nix 코드 조각입니다. NixOS에서 모듈은 속성 집합을 받아 또 다른 속성 집합을 반환하는 함수입니다. 모듈의 기본 구조는 다음 코드 조각에서 확인할 수 있습니다: ```nix title="/etc/nixos/configuration.nix" { lib, config, pkgs, ... }: { imports = []; config = {}; options = {}; } ``` NixOS를 처음 살펴보면 `/etc/nixos/`에 있는 `configuration.nix` 파일을 틀림없이 보게 됩니다. 또한 다른 사람의 NixOS 설정을 보면 이와 똑같은 구조가 아닐 수도 있습니다. 우선 입력 집합은 짧게 줄여 쓸 수 있습니다(가장 극단적인 경우 `{ ... }`까지 줄일 수 있습니다). 이것이 어떤 역할을 하는지에 대한 자세한 내용은 [Nix 구문](/zero-to-nix/concepts/nix) 섹션을 참고하십시오. 또한 NixOS 모듈에는 몇 가지 문법적 편의 기능이 있어서, 모듈이 `options`를 하나도 선언하지 않는다면 `config` 키를 생략할 수 있습니다. 예를 들어 다음 두 모듈은 서로 동등합니다. ```nix title="Equivalent NixOS modules" # Module 1 { ... }: { imports = [ ./my-fish-config.nix ]; programs.fish.enable = true; } # Module 2 { ... }: { imports = [ ./my-fish-config.nix ]; config = { programs.fish.enable = true; }; } ``` ### 모듈 사용 방법 먼저 NixOS [모듈 검색][search]에서 사용할 모듈과 그 사용 방법을 찾을 수 있습니다. Nix 모듈은 일반적으로 [선언형][declarative] 원칙을 따릅니다. 즉, 모듈이 실행되는 정해진 순서가 없습니다. 대신 시스템에서 원하는 결과를 기술하면 Nix가 그 결과를 만들어 줍니다. 다음은 [nginx] 웹 서버를 설치하고 설정하는 방법의 예시입니다. ```nix title="nginx web server example" { ... }: { services.nginx = { enable = true; virtualHosts."default" = { forceSSL = true; # Redirect HTTP clients to an HTTPs connection default = true; # Always use this host, no matter the host name root = /var/www/my-website; # Set the web root to serve }; }; } ``` ## 릴리스 NixOS는 매년 두 차례 주요 [릴리스][releases]를 냅니다. 릴리스 슬러그는 `{year}.{month}` 형식이므로 `22.05`는 2022년 5월, `20.09`는 2020년 9월에 해당하는 식입니다. NixOS는 Nix로 설정하므로 특정 패키지와 의존성을 원하는 리비전으로 언제든지 [고정][pin]할 수 있습니다. [apt]: https://en.wikipedia.org/wiki/APT_(software) [boot]: https://wiki.nixos.org/wiki/Bootloader [declarative]: /concepts/declarative [derivations]: /concepts/derivations [dpkg]: https://debian.org/doc/manuals/debian-faq/pkgtools [fhs]: https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard [filesystem]: https://nixos.org/manual/nixos/stable/#ch-file-systems [git]: https://git-scm.com [kernel]: https://wiki.nixos.org/wiki/Linux_kernel [lang]: /concepts/nix-language [linux]: https://kernel.org [nginx]: https://nginx.org [nix]: /concepts/nix [openssh]: https://openssh.com [packages]: /concepts/packages [pin]: /concepts/pinning [pkg]: /concepts/package-management [realised]: /concepts/realisation [rebuild]: https://wiki.nixos.org/wiki/Nixos-rebuild [releases]: https://nixos.org/blog/announcements [search]: https://search.nixos.org/options [store]: /concepts/nix-store [window]: https://wiki.nixos.org/wiki/Category:Window_managers --- **Nixpkgs** Published: URL: https://zero-to-nix.com//concepts/nixpkgs _Nixpkgs_("Nix packages"로 발음합니다)는 Nix 생태계를 위한 [Nix] 표현식, 패키지(누가 예상했겠습니까...), 빌드 유틸리티의 방대한 모음입니다. "Nix 표준 라이브러리"(또는 Nix stdlib)라고 부르기도 합니다. Nixpkgs는 10만 개가 훨씬 넘는 패키지 정의와 이 패키지 집합을 유지 관리하기 위한 유틸리티를 담고 있는 모노 저장소입니다. 또한 [NixOS](/zero-to-nix/concepts/nixos) 모듈을 비롯해 완전한 Nix 시스템을 빌드하고 배포하는 데 필요한 모든 것을 포함합니다. Nix 생태계의 많은 도구가 이 표준 라이브러리에 의존하여 동작합니다. [nix]: https://nixos.org --- **패키지 관리** Published: URL: https://zero-to-nix.com//concepts/package-management *패키지 관리*는 소프트웨어 [패키지][packages]를 빌드하고 배포하는 기술입니다. [Nix]는 몇 가지 중요한 면에서 [apt], [dpkg], [yum] 같은 패키지 관리자와 다릅니다. - Nix는 항상 모든 [패키지][packages]를 처음부터 빌드하며, 여기에는 해당 패키지의 [클로저][closure], 즉 의존성 트리 전체가 포함됩니다. 하지만 의존성이 이미 [Nix 스토어][store]나 원격 캐시에 있으면 Nix는 그것을 다시 빌드하는 대신 사용할 수 있습니다. 따라서 Nix는 [증분 빌드][incremental]를 제공할 수 있습니다. - Nix에는 직접 패키지 빌드를 정의하는 데 사용할 수 있는 [언어][language]가 있으며, 이 언어의 이름도 *Nix*입니다. - Nix는 Linux, macOS, Windows WSL을 비롯한 여러 플랫폼에서 작동합니다. [apt]: https://en.wikipedia.org/wiki/APT_(software) [closure]: /concepts/closures [dpkg]: https://man7.org/linux/man-pages/man1/dpkg.1.html [incremental]: /concepts/incremental-builds [language]: /concepts/nix-language [nix]: /concepts/nix [packages]: /concepts/packages [store]: /concepts/nix-store [yum]: https://es.wikipedia.org/wiki/Yum_(software) --- **패키지** Published: URL: https://zero-to-nix.com//concepts/packages Nix *패키지*는 [derivation][derivations]을 사용해 빌드되는 독립적인 번들로, 컴퓨터에 특정 소프트웨어나 소프트웨어의 의존성을 제공합니다. 패키지는 다른 패키지에 대한 의존성을 가질 수 있으며, 이러한 의존성은 해당 패키지의 [클로저][closure]에 기록됩니다. 각 패키지는 [Nix 스토어](/zero-to-nix/concepts/nix-store) 안의 고유한 경로에 위치하며, 이 경로는 패키지의 이름과 입력 해시로 색인됩니다. [closure]: /concepts/closures [derivations]: /concepts/derivations --- **의존성 고정** Published: URL: https://zero-to-nix.com//concepts/pinning 의존성을 *고정*한다는 것은 Nix가 사용할 정확한 리비전을 지정하는 것을 말합니다. 이는 Nix의 [재현성](/zero-to-nix/concepts/reproducibility) 보장과 관련하여 특히 흥미로운 부분입니다. Nix 의존성을 특정 리비전으로 고정하면, 변경될 수 없는 동일한 입력을 바탕으로 항상 동일한 빌드 출력을 얻을 수 있음이 보장됩니다. 이는 서로 다른 개발자 간에, 또는 개발 환경과 프로덕션 환경 간에 환경을 공유할 때 특히 유용합니다. 의존성 고정은 플레이크 파일의 `inputs` 섹션에서 할 수 있습니다: ```nix title="flake.nix" { inputs = { nixpkgs.url = "git+https://github:nixos/nixpkgs?rev=fdc8ef970de2b4634e1b3dca296e1ed918459a9e"; }; } ``` --- **출처** Published: URL: https://zero-to-nix.com//concepts/provenance *출처*는 기본적으로 어떤 것의 기원과 같은 뜻으로 쓰이는 용어입니다. 소프트웨어에서 출처는 보통 산출물(프로그램, 파일, 스마트폰 앱 등)을 만든 빌드 과정을 가리킵니다. 소프트웨어가 어떤 코드로 빌드되었는지, 어느 서버에서 다운로드되었는지와 같은 출처를 확인하지 않으면 그 소프트웨어를 얼마나 신뢰해야 할지 알기 어렵습니다. 그 소프트웨어는 신뢰할 수 있는 사람들이 만든 유용한 소프트웨어입니까? 아니면 유용한 소프트웨어로 위장한 채 파일 시스템에서 비밀 정보를 캐내거나 비트코인을 채굴하는 것처럼 원치 않는 일을 하고 있습니까? 그 소프트웨어의 출처를 확인하면 보통 이 질문에 답하는 데 도움이 됩니다. --- **실체화** Published: URL: https://zero-to-nix.com//concepts/realisation *실체화*는 Nix [derivation]이 [패키지][package]로 변환되는 과정입니다. derivation이 본질적으로 패키지에 대한 계획이라면, 실체화는 그 계획을 내용으로 가득 찬 실제 출력 디렉터리로 바꾸는 빌드 과정입니다. ## `.drv` 파일 패키지를 빌드하기 위해 [`nix build`][nix-build]를 실행하면, Nix CLI는 먼저 해당 함수의 [`derivation`][derivation] 함수를 살펴보고 이를 중간 단계의 [`.drv` 파일][drv]로 변환합니다. 이 파일은 본질적으로 `derivation` 함수를 형식적으로 표현한 것입니다. 모든 `.drv` 파일은 `/nix/store/m2nb4d0pfydr8bq5ww1yqbrkvvf18zbl-perl-5.36.0.drv`와 같이 해시가 포함된 경로로 [Nix 스토어][store]에 저장되며, 이를 통해 `derivation` 함수에 _어떤_ 변경이라도 생기면 새 경로를 가진 새 `.drv` 파일이 만들어지도록 보장합니다. 그런 다음 CLI는 `.drv` 파일을 실제 빌드 과정의 청사진으로 사용하며, 이 빌드 과정에서는 항상 패키지의 전체 의존성 트리를 빌드합니다. ## 빌드 과정 Nix는 derivation에 대한 `.drv` 파일을 만든 뒤, 파일에 인코딩된 명령을 사용해 [샌드박스][sandboxed] 환경에서 실제로 패키지를 빌드합니다. 이는 본질적으로 실체화가 `/etc`의 설정 파일과 같은 머신의 전역 상태에 의존하지도, 영향을 주지도 않는다는 뜻입니다. 빌드 과정에 필요한 모든 것은 다음에서 가져옵니다. 1. derivation의 빌드 명령입니다. 예를 들어 `cat`, `touch`, `mkdir`, `mv`와 같은 명령입니다. 1. [Nix 스토어][store]의 산출물입니다. 예를 들어 [Git]을 빌드 입력으로 하는 derivation을 작성하면, 실체화 과정은 Git을 빌드하여 그 결과 패키지를 (아직 빌드되어 저장되어 있지 않은 경우) [Nix 스토어][store]에 저장하고, 빌드 로직에서 `git` 명령이 호출될 때 `/usr/bin/git`과 같은 경로에 있는 "전역" Git 대신 그 패키지를 사용합니다. [derivation]: /concepts/derivations [drv]: https://nixos.org/guides/nix-pills/our-first-derivation [git]: https://git-scm.com [nix-build]: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix3-build [package]: /concepts/packages [sandboxed]: /concepts/sandboxing [store]: /concepts/nix-store --- **재현성** Published: URL: https://zero-to-nix.com//concepts/reproducibility *재현성*은 같은 입력에 대한 연산이 같은 출력을 내는 소프트웨어 설계 개념입니다. 해시는 빌드의 입력을 바탕으로 만들어지므로 같은 입력이 같은 빌드 출력을 낸다는 점이 반드시 보장되어야 합니다. 이 때문에 이는 Nix에서 중요한 특성입니다. ```nix title="Example derivation" { stdenv, fetchGit }: stdenv.mkDerivation { name = "my-package"; src = fetchgit { url = "https://github.com/DeterminateSystems/riff"; sha256 = "sha256-7mnx7J0AacL2P2mNuNNB+kKE7VR8nniVG+PSrwpZixE="; }; } ``` 위 코드는 `fetchgit`과 `mkDerivation`이라는 _두_ derivation으로 구성되어 있습니다. `fetchgit`의 출력이 특정 해시로 고정되어 있으므로 `mkDerivation`의 재현성이 보장됩니다. 또한 `mkDerivation` 자체는 네트워크에 접근할 수 없고 호스트로부터 [밀폐](/zero-to-nix/concepts/hermeticity)되어 있으므로, 빌드에 불순한 요소가 존재할 수 없습니다. `fetchgit`의 출력은 특정 해시로 고정되어 있으므로 보장됩니다. 네트워크에 접근*할 수는* 있지만, 가져온 결과가 사용자가 제공한 출력 해시와 일치하지 않으면 빌드에 실패합니다. 이처럼 Nix 빌드의 재현성이 마치 패키징 양파처럼 여러 겹으로 쌓여 있음을 알 수 있습니다. --- **샌드박싱** Published: URL: https://zero-to-nix.com//concepts/sandboxing Nix는 무언가를 빌드할 때마다 해당 프로세스를 호스트 시스템의 다른 모든 것으로부터 *샌드박스*로 격리합니다. Nix 빌드가 샌드박스 안에서 실행되는 데에는 여러 가지 이유가 있습니다. 1. [재현성][reproducibility]을 보장하기 위해서입니다. 샌드박싱은 호스트 머신의 어떤 시스템 상태도 빌드 결과에 영향을 미치지 않도록 보장합니다. 1. 엄격한 [출처][provenance]를 유지하기 위해서입니다. [reproducibility]: /concepts/reproducibility [provenance]: /concepts/provenance --- **시스템 특정성** Published: URL: https://zero-to-nix.com//concepts/system-specificity Nix에서 *시스템 종속성*이라는 용어는 모든 Nix [derivation][derivations]이 해당 derivation이 어떤 시스템에서 빌드되는지를 지정하는 `system` 속성을 가진다는 사실을 나타냅니다. Nix derivation을 [패키지][package]로 실체화하려면 해당 패키지의 클로저에 속한 각 derivation이 대상 시스템에서 지원되어야 합니다. 따라서 `x86_64-linux` 시스템에서 `foo` 패키지를 빌드하려면 `foo` derivation의 모든 의존성이 `x86_64-linux`에서 지원되어야 합니다. 시스템 특정성은 Nix가 진정한 멀티 플랫폼 시스템이 되는 데 필수적입니다. 모든 derivation이—따라서 모든 패키지가—시스템에 종속적이므로 Nix [개발 환경][env]이나 [NixOS] 설정 같은 것들도 시스템에 종속적입니다. [derivations]: /concepts/derivations [env]: /concepts/dev-env [nixos]: /concepts/nixos [package]: /concepts/packages --- ## Other formats For additional LLM-oriented manifests, see also: - [`llms-small.txt`](https://zero-to-nix.com/llms-small.txt) (compact structure-only version) - [`llms.txt`](https://zero-to-nix.com/llms.txt) (the main version) ## Other Determinate Systems projects These other projects under the Determinate Systems umbrella have their own LLM-oriented manifests: - [FlakeHub](https://flakehub.com/llms.txt) (FlakeHub is a platform for publishing and discovering Nix flakes and Nix artifacts, featuring semantic versioning, private flakes with federated, JWT-based authentication, flake discovery via search, labels, and other means, and next-generation Nix binary caching with FlakeHub Cache.) - [Determinate documentation](https://docs.determinate.systems/llms.txt) (Determinate is Nix for teams: Stop wrestling with binary caches, reinventing deploy scripts, and figuring out access controls. Confidently adopt and scale Nix across teams of any size.) - [Determinate Systems website](https://determinate.systems/llms.txt) (Our goal for Determinate is to enable fearless innovation by bringing Nix to teams, providing a complete Nix-based workflow from installation through collaboration and CI to deployment.)