Appendix A. Nix Flakes: 완전한 재현성 보장
A.1 기존 방식의 한계
shell.nix의 재현성 문제
# 목적: 기존 방식의 문제점 파악
# 문제점: nixpkgs 버전 미고정
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = with pkgs; [
python38
python38Packages.pandas
];
}
문제: <nixpkgs>
가 시스템 채널에 의존하여 시점에 따라 다른 환경 생성
# 2023년 10월 실행
$ nix-shell basic-env.nix
Python 3.8.16, pandas 1.5.3
# 2024년 3월 실행 (nixpkgs 업데이트 후)
$ nix-shell basic-env.nix
Python 3.8.18, pandas 2.0.1 # 다른 버전
A.2 Flakes 개념
정의와 구조
Flake는 프로젝트의 모든 의존성을 명시적으로 선언하고 버전을 정확히 고정하는 시스템입니다.
핵심 파일:
flake.nix
: 의존성과 출력 정의flake.lock
: 정확한 버전 해시 (자동 생성)
기본 구조
# 목적: Flake 기본 구조 이해
# 핵심 개념: inputs, outputs, 버전 고정
{
description = "개발 환경 프로젝트";
# 모든 외부 의존성 명시
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
};
# 제공할 출력들 정의
outputs = { self, nixpkgs }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.${system}.default = pkgs.mkShell {
buildInputs = with pkgs; [
python38
python38Packages.pandas
];
};
};
}
A.3 다중 환경 Flake
환경별 구성
# 목적: 프로젝트 단계별 환경 제공
# 핵심 개념: 다중 출력, 조합성
{
description = "데이터 분석 프로젝트";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
};
outputs = { nixpkgs, ... }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
mkPythonEnv = extraPackages: pkgs.mkShell {
buildInputs = with pkgs; [
python38
python38Packages.pandas
python38Packages.numpy
] ++ extraPackages;
};
in {
devShells.${system} = {
# 기본 분석 환경
default = mkPythonEnv (with pkgs; [
python38Packages.matplotlib
]);
# 기계학습 환경
ml = mkPythonEnv (with pkgs; [
python38Packages.tensorflow
python38Packages.scikit-learn
]);
# 웹 개발 환경
web = mkPythonEnv (with pkgs; [
python38Packages.flask
python38Packages.requests
]);
};
};
}
사용법
# 기본 환경
$ nix develop
# 특정 환경
$ nix develop .#ml
$ nix develop .#web
A.4 실제 프로젝트 구성
프로젝트 구조
data-analysis/
├── flake.nix
├── flake.lock
├── src/
│ ├── analysis.py
│ └── utils.py
├── data/
│ └── dataset.csv
└── README.md
완전한 프로젝트 Flake
# 목적: 실무 프로젝트 설정
# 핵심 개념: 개발도구 통합, 스크립트 제공
{
description = "데이터 분석 프로젝트";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
};
outputs = { nixpkgs, ... }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.${system}.default = pkgs.mkShell {
buildInputs = with pkgs; [
# Python 환경
python38
python38Packages.pandas
python38Packages.matplotlib
python38Packages.jupyter
# 개발 도구
git
black # 코드 포매터
];
shellHook = ''
echo "데이터 분석 환경"
echo "데이터: $(ls data/ | wc -l) 파일"
echo ""
echo "사용법:"
echo " python src/analysis.py"
echo " jupyter notebook"
'';
};
# 분석 스크립트를 앱으로 제공
apps.${system}.analysis = {
type = "app";
program = "${pkgs.python38}/bin/python";
args = [ "src/analysis.py" ];
};
};
}
A.5 버전 관리
flake.lock 파일
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1697723726,
"narHash": "sha256-SaTWPkI8a5xSHX/rrKzUe9...",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7816540796e4f6b4f1a1e8c45be6c54f9e1b8db7",
"type": "github"
}
}
}
}
의미: 정확한 커밋 해시로 nixpkgs 버전 고정하여 재현성 보장
업데이트 관리
# 현재 버전 확인
$ nix flake metadata
# 의존성 업데이트
$ nix flake update
# 특정 입력만 업데이트
$ nix flake update nixpkgs
A.6 팀 협업
Git 통합
# 프로젝트 초기화
$ git init
$ git add flake.nix flake.lock src/ data/
$ git commit -m "프로젝트 초기 설정"
팀원 환경 구성
# 저장소 복제
$ git clone https://github.com/team/data-project.git
$ cd data-project
# 환경 즉시 사용
$ nix develop # flake.lock 기반으로 동일한 환경 구성
A.7 기존 프로젝트 마이그레이션
shell.nix → flake.nix 변환
기존:
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = with pkgs; [ python38 git ];
}
변환 후:
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11";
outputs = { nixpkgs, ... }: {
devShells.x86_64-linux.default =
nixpkgs.legacyPackages.x86_64-linux.mkShell {
buildInputs = with nixpkgs.legacyPackages.x86_64-linux; [
python38 git
];
};
};
}
요약: Flakes는 모든 의존성을 명시적으로 관리하여 완전한 재현성을 보장합니다. 프로젝트와 환경을 하나의 단위로 관리하여 팀 협업과 장기 보존에 필수적입니다.