3. Nix 개발 환경 살펴보기
→nix develop 명령으로 Nix 개발 환경 활성화하기
→개발 환경에 실제로 들어가지 않고 그 안에서 명령 실행하기
→특정 프로그래밍 언어에 맞춘 Nix 개발 환경 살펴보기
→여러 요소가 섞인 개발 환경 살펴보기
→nix develop으로 로컬 플레이크에 정의된 환경 활성화하기
소프트웨어 개발을 위한 Nix의 핵심 기능 중 하나는 Nix 개발 환경입니다. Nix 언어를 사용하면 복잡도와 상관없이 어떤 개발 환경이든 정의할 수 있습니다. 이 내용은 조금 뒤에 다루겠지만, 지금은 Nix 개발 환경이 무엇이고 어떻게 동작하는지 감을 잡아 봅시다.
nix develop 명령은 Nix 환경을 활성화합니다:
nix develop "https://flakehub.com/f/DeterminateSystems/zero-to-nix/*#example"다음과 같은 새 셸 프롬프트가 나타날 것입니다:
(nix:zero-to-nix-env) bash-5.2$🚀 성공입니다! 이제 curl과 Git이 포함된 Bash 환경에 들어와 있습니다. 두 가지 모두 이미 환경에 있을 수도 있지만, 무언가 새로운 일이 일어나고 있음을 확인하려면 다음 명령을 실행하십시오:
type curltype git예를 들어 curl의 경우 다음과 같은 낯선 경로가 보일 것입니다(해시 부분은 여러분의 컴퓨터에서 다를 것입니다):
/nix/store/
1. Nix 스토어 접두사
sglc12hc6pc68w5ppn2k56n6jcpaci16
2. 해시 부분
-
curl-8.1.1-bin
3. 패키지 이름
/
bin/curl
4. 프로그램 경로
여기서 무슨 일이 일어났습니까? Nix CLI는 몇 가지 작업을 수행했습니다:
https://flakehub.com/f/DeterminateSystems/zero-to-nix/*#example플레이크 참조를 사용해 Nix 코드를 가져오고 특정 플레이크 출력을 빌드했습니다(자세한 내용은 뒤에서 다룹니다).- 환경 설정에 지정된 패키지를 빌드했습니다(이 역시 자세한 내용은 뒤에서 다룹니다).
- Nix 스토어에서
git과curl패키지를 찾을 수 있도록PATH가 설정된 환경을 구성했습니다.
Nix 개발 환경에서 제공할 수 있는 다른 두 가지는 다음과 같습니다:
-
이 예제에는 포함되어 있지 않지만, 환경이 시작될 때마다 실행되는 임의의 셸 코드인 셸 훅을 정의할 수 있습니다. 셸 훅의 사용 사례 예시는 다음과 같습니다:
-
환경이 활성화될 때마다 환경에 대한 정보를 콘솔에
echo합니다 -
검사나 린터 같은 작업을 실행합니다
-
Git 훅 같은 다른 필요한 훅이 제대로 설정되어 있는지 확인합니다. 셸 훅 예제를 보려면 다음을 실행하십시오:
Run a shell hook nix develop "github:DeterminateSystems/zero-to-nix#hook"
-
-
Nix 개발 환경은 환경 변수도 지원합니다.
echo $FUNNY_JOKE를 실행하면 Nix 환경에서만 사용할 수 있는 (아주 재미있는) 값을 확인할 수 있습니다. 환경 변수의 사용 사례는 다음과 같습니다:LOG_LEVEL이나 사용 중인 도구에 맞는 변수로 로깅 수준을 설정합니다.NODE_ENV(Node.js용) 같은 변수를 사용해 환경을development,dev등으로 설정합니다.
다음 섹션을 준비하기 위해 Nix 개발 환경에서 나갑시다:
exitGit이 설치되어 있다면 type git을 사용해 PATH에서 Git의 위치를 확인하십시오. /usr/bin/git 같은 전역 경로에 있을 것입니다. 그리고 echo $FUNNY_JOKE를 다시 실행하면 빈 문자열이 출력될 것입니다(마침 여러분의 컴퓨터에 그 변수가 설정되어 있는 경우가 아니라면 말입니다!).
개발 환경 안에서 명령 실행하기
환경을 탐색하는 것은 재미있지만, 환경을 사용하기 위해 매번 그 안에 들어가고 싶지는 않을 것입니다. nix develop 명령은 --command(또는 -c) 플래그를 제공하며, 이 플래그를 사용하면 현재 환경에서 해당 환경을 사용하는 명령을 실행할 수 있습니다. 앞서 사용한 환경에 대한 몇 가지 예시는 다음과 같습니다:
nix develop "https://flakehub.com/f/DeterminateSystems/zero-to-nix/*#example" --command git helpnix develop "https://flakehub.com/f/DeterminateSystems/zero-to-nix/*#example" --command curl https://example.com두 경우 모두 Nix 스토어에 있는 패키지를 실행하며, 전역 환경의 것은 전혀 사용하지 않습니다. 보시다시피 Nix 개발 환경은 주변 환경(환경 변수나 /bin, /usr/bin 같은 경로 등)으로부터 격리되어 있다는 점에서 밀폐되어 있습니다.
언어별 환경
이전 섹션에서 했던 것처럼, 조금 더 구체적으로 들어가 Nix가 특정 프로그래밍 환경에 어떤 이점을 줄 수 있는지 살펴봅시다. 다음 프로그래밍 언어 중 하나를 선택하십시오:
언어를 선택하세요
이제 용 Nix 개발 환경을 살펴봅시다:
nix develop "github:DeterminateSystems/zero-to-nix#cpp"먼저 CMake의 Nix 스토어 경로를 확인해 봅시다:
type cmake현재 CMake 버전을 확인하십시오:
cmake --versionnix develop "github:DeterminateSystems/zero-to-nix#haskell"먼저 Glasgow Haskell Compiler(GHC)의 Nix 스토어 경로를 확인해 봅시다:
type ghc현재 GHC 버전을 확인하십시오:
ghc --versionnix develop "github:DeterminateSystems/zero-to-nix#javascript"먼저 Node.js의 Nix 스토어 경로를 확인해 봅시다:
type node이제 Node를 사용해 프로그램을 실행하십시오:
node --eval "console.log('1 + 1 = ' + (1 + 1))"nix develop "github:DeterminateSystems/zero-to-nix#python"먼저 Python의 Nix 스토어 경로를 확인해 봅시다:
type python이제 Python을 사용해 프로그램을 실행하십시오:
python -c "print(1 + 1)"nix develop "github:DeterminateSystems/zero-to-nix#go"먼저 Go CLI의 Nix 스토어 경로를 확인해 봅시다:
type go이제 Go 버전을 확인하십시오:
go versionnix develop "github:DeterminateSystems/zero-to-nix#rust"먼저 cargo의 Nix 스토어 경로를 확인해 봅시다:
type cargo이제 현재 디렉터리에 Rust 프로젝트를 생성하고 예제를 실행하십시오:
cargo init ./zero-to-nix-rscd ./zero-to-nix-rscargo runHello, world!가 출력될 것입니다.
nix develop "github:DeterminateSystems/zero-to-nix#scala"먼저 sbt의 Nix 스토어 경로를 확인해 봅시다:
type sbt환경 안에서 sbt 버전을 확인하십시오:
sbt --version평소처럼 exit를 실행하여 Nix 환경을 벗어나 원래 환경으로 돌아가십시오.
언어별 환경을 넘어서
이전 섹션에서는 특정 프로그래밍 언어에 맞춘 Nix 환경을 살펴보았습니다. 하지만 Nix 환경은 무한히 유연하므로 원하는 패키지를 무엇이든 조합할 수 있습니다. 그 예시를 살펴봅시다:
nix develop "https://flakehub.com/f/DeterminateSystems/zero-to-nix/*#multi"이 Nix 환경에서는 여러 도구를 사용할 수 있습니다:
앞의 예시와 마찬가지로 type python, type kubectl 같은 명령을 실행하면 이 도구들이 모두 /usr/bin 같은 곳이 아니라 Nix 스토어에서 발견된다는 것을 확인할 수 있습니다. 이 목록에는 패키지 100개도 쉽게 넣을 수 있습니다. 이는 여러분이 정하기 나름입니다. 이러한 환경을 어떻게 만드는지는 아직 다루지 않겠지만, 이 가이드를 통해 Nix 개발 환경이 무엇을 제공하는지 기본적인 감을 얻으시기를 바랍니다.
direnv는 디렉터리로 cd할 때마다 특정 환경 변수를 자동으로 불러오는(그리고 디렉터리에서 cd로 나갈 때 해당 변수를 해제하는) 인기 있는 도구입니다. direnv와 Nix를 함께 사용하면 디렉터리로 이동할 때마다 Nix 개발 환경을 자동으로 불러올 수 있어 상당히 강력합니다. 자세한 내용은 Determinate Systems 블로그의 Nix와 direnv로 손쉽게 만드는 개발 환경을 참조하십시오.
로컬 플레이크에서
이 가이드의 앞부분에서는 FlakeHub에 있는 플레이크에 정의된 Nix 개발 환경을 활성화했습니다. 이런 방식으로 환경을 사용하는 것도 유용하지만, 현재 디렉터리의 로컬 플레이크에 정의된 개발 환경을 사용하는 것이 더 일반적입니다.
먼저 선호하는 언어를 알려 주십시오:
언어를 선택하세요
프로젝트를 시작하려면 빈 디렉터리를 만들고 플레이크 템플릿을 초기화하십시오:
mkdir nix-cpp-dev && cd nix-cpp-devnix flake init --template "github:DeterminateSystems/zero-to-nix#cpp-dev"mkdir nix-haskell-dev && cd nix-haskell-devnix flake init --template "github:DeterminateSystems/zero-to-nix#haskell-dev"mkdir nix-javascript-dev && cd nix-javascript-devnix flake init --template "github:DeterminateSystems/zero-to-nix#javascript-dev"mkdir nix-python-dev && cd nix-python-devnix flake init --template "github:DeterminateSystems/zero-to-nix#python-dev"mkdir nix-go-dev && cd nix-go-devnix flake init --template "github:DeterminateSystems/zero-to-nix#go-dev"mkdir nix-rust-dev && cd nix-rust-devnix flake init --template "github:DeterminateSystems/zero-to-nix#rust-dev"mkdir nix-scala-dev && cd nix-scala-devnix flake init --template "github:DeterminateSystems/zero-to-nix#scala-dev"템플릿이 초기화되면 ls .를 실행하여 디렉터리의 내용을 확인하십시오. 다음 두 가지 중요한 파일이 있어야 합니다:
flake.nix파일은 프로젝트의 플레이크를 정의합니다.flake.lock은flake.nix파일에 있는 모든 플레이크 입력—본질적으로 Nix 의존성—을 특정 Git 리비전으로 고정합니다.
이 Nix 플레이크의 플레이크 출력 중 하나는 용 개발 환경입니다. 해당 개발 환경에 들어가려면 다음을 실행하십시오:
nix develop이제 개발 환경에 들어왔으니 Nix 스토어 경로부터 시작하여 몇 가지를 살펴보겠습니다.
일반적으로 Unix 시스템에서 type gcc를 실행하면 /usr/bin/gcc 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오:
type gcc다음과 같은 (다소 이상한) 경로가 보일 것입니다:
gcc is /nix/store/nbrvvx1gyq3as3ghmjz62wlgd8f3zfpf-gcc-wrapper-11.3.0/bin/gcc일반적으로 Unix 시스템에서 type ghc를 실행하면 /usr/bin/ghc 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오:
type ghc다음과 같은 (다소 이상한) 경로가 보일 것입니다:
ghc is /nix/store/f3qnvw5gxgxxpr275kf97pfcy2n1gv79-ghc-9.2.4/bin/ghc일반적으로 Unix 시스템에서 type node를 실행하면 /usr/bin/node 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오:
type node다음과 같은 (다소 이상한) 경로가 보일 것입니다:
node is /nix/store/i88kh2fd03f5fsd3a948s19gliggd2wd-nodejs-18.12.1/bin/node일반적으로 Unix 시스템에서 type python을 실행하면 /usr/bin/python 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오:
type python다음과 같은 (다소 이상한) 경로가 보일 것입니다:
python is /nix/store/a9mmam4km4bjnkzl62533w7d0wyrhrj9-python3-3.13.6/bin/python일반적으로 Unix 시스템에서 type go를 실행하면 /usr/bin/go 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오:
type go다음과 같은 (다소 이상한) 경로가 보일 것입니다:
go is /nix/store/5bcx8rv6sy33xsf5dzkp9q8lfdqrsiwa-go-1.19.4/bin/go일반적으로 Unix 시스템에서 type cargo를 실행하면 /usr/bin/cargo 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오:
type cargo다음과 같은 (다소 이상한) 경로가 보일 것입니다:
cargo is /nix/store/zc1nr87147gvmg5nqci8q5cfnzg82vwp-rust-default-1.64.0/bin/cargo일반적으로 Unix 시스템에서 type sbt를 실행하면 /usr/bin/sbt 같은 경로가 나옵니다. Nix 개발 환경에서 실행해 보십시오:
type sbt다음과 같은 (다소 이상한) 경로가 보일 것입니다:
sbt is /nix/store/p0hca7x8g45p5hnh0xjzy5s2bcpy1i9l-sbt-1.7.3/bin/sbt아마 예상하신 결과는 아닐 것입니다! 여기서 무슨 일이 일어났습니까? 몇 가지 일이 일어났습니다: