본문으로 건너뛰기

"tools" 태그로 연결된 2개 게시물개의 게시물이 있습니다.

모든 태그 보기

‘순수 함수형’ 패키지 관리자 Nix 맛보기

· 약 9분

Nix는 Linux와 macOS를 지원하는 패키지 관리 시스템입니다.

해커 뉴스 등에서 Nix에 대해 종종 접하게 되어서 궁금증이 생겼고, 조금 사용해보면서 파악한 내용을 정리합니다. 계속 사용할지는 아직 모르겠지만 이것저것 찾아보느라 들인 시간이 아까우니까요. 누군가에겐 도움이 되겠죠?

Nix에는 여러 특징이 있지만, 그 중에서도 같은 패키지의 여러 버전을 동시에 설치할 수 있어서 패키지를 한번 설치하면 시스템에 변화가 있더라도 계속 작동이 보장된다는 점이 유용해 보입니다. 이런 특징을 활용하면 프로젝트마다 독립된 개발 환경을 구축하는 데에 쓸 수 있습니다.

의존성 지옥!

APT나 Homebrew 등 일반적인 패키지 관리 시스템에서는 시스템 전역에 특정 패키지 이름으로는 딱 한가지 버전만 설치할 수 있습니다. 이를 우회하기 위해 패키지 이름에 버전을 명시하기도 합니다. (예를 들면 python3.9python3.10을 별개의 패키지로 배포하는 등)

여러 패키지가 하나의 공통 패키지에 의존하는 경우 특히 문제가 있습니다. 예를 들어 OpenSSL 같은 라이브러리를 업그레이드하면 OpenSSL에 직간접적으로 의존하는 모든 패키지가 영향을 받습니다.

패키지마다 호환되는 의존성의 버전을 느슨하게 정의해두고 있기는 하지만, 운이 나쁘면 이전과 똑같이 작동하지 않을 수 있습니다. 그리고 업그레이드하려는 버전이 어떤 패키지에서 요구하는 버전과 충돌하는 경우 아예 업그레이드를 못할 수도 있습니다.

Nix에서는 의존성을 yc41q33h5xrw1zbyw5hp1y1ga0jk9hwd-openssl-1.1.1k과 같이 정확한 버전과 특정 빌드로 정의합니다. 따라서 패키지마다 각자 독립적으로 의존성의 버전을 선택할 수 있습니다. 패키지끼리 서로 영향을 주지 않기 때문에 안전하게 패키지를 설치하거나 업그레이드할 수 있습니다. 또한 의존성이 고정되므로 패키지가 저자의 의도대로 작동할 가능성이 높아집니다.

Nix 맛보기

nix-shell을 사용하면 특정 Nix 패키지가 설치된 환경을 여러개 만들 수 있습니다. 예제로 Python과 Node가 설치된 환경을 만들어보겠습니다.

먼저 Nix를 설치합니다.

프로젝트 디렉토리에 shell.nix 파일을 만들고 다음 내용을 추가합니다.

let
pkgs = import <nixpkgs> {};
in pkgs.mkShell {
nativeBuildInputs = [
pkgs.python3
pkgs.nodejs
];
}

그 다음 해당 디렉토리에서 nix-shell을 실행하면 필요한 패키지를 다운로드 받고 새로운 쉘이 켜집니다. 이 쉘 환경에서는 python, node/nix/store 하위에 설치된 특정 바이너리를 가리키고 있는 것을 확인할 수 있습니다.

~/myproject$ nix-shell
these paths will be fetched (...):
(생략)

[nix-shell:~/myproject]$ which python
/nix/store/d44wd6n98f93hjr6q1d1phhh1hw7a17d-python3-3.8.8/bin/python

[nix-shell:~/myproject]$ which node
/nix/store/y9ay04l5mfm255r296vhcjbxjqkjxp39-nodejs-14.16.1/bin/node

패키지를 추가하자

shell.nix가 무언가 생소한 언어로 작성되어서 혼란스러울 것입니다. 사실 이것은 Nix expression language 코드이지만 일단은 설명하지 않겠습니다.

중요한 부분은 nativeBuildInput입니다. python3, node 외에 다른 패키지는 Nixpkgs에서 검색해서 찾으면 됩니다. Channel을 unstable로 설정해서 찾아야 합니다. 그리고 macOS를 지원하지 않는 패키지가 종종 있으므로 Platforms에 x86_64-darwin가 있는지 확인합시다.

패키지를 찾았다면 pkgs.패키지명을 추가하고, nix-shell에서 나갔다가 (Ctrl-D 입력) 다시 nix-shell을 실행하면 해당 패키지가 추가된 환경으로 들어갈 수 있습니다.

Nixpkgs를 고정하자

2번째 줄 pkgs = import <nixpkgs> {};에서 <nixpkgs>는 시스템 전역에 설정된 채널을 따라가기 때문에 계속 변할 수 있는 값입니다. 정말 개발 환경이 항상 같으려면 Nixpkgs를 특정 버전으로 고정해야합니다.

이를 위해 niv를 사용하겠습니다. 프로젝트 디렉토리에서 다음 명령을 실행합니다.

nix-shell -p niv --run "niv init -b nixpkgs-unstable"

그러면 nix/sources.json, nix/sources.nix가 생성됩니다. 이제 shell.nix를 수정해서 고정된 Nixpkgs를 사용하도록 설정합니다.

let
sources = import ./nix/sources.nix;
pkgs = import sources.nixpkgs {};
in pkgs.mkShell {
...
}

direnv를 연동하자

매번 적절한 nix-shell을 켜는 것은 불편하므로 direnv를 활용하면 좋습니다.

direnv도 Nix를 활용해서 설치해보겠습니다. (이미 direnv가 설치되어 있다면 넘어가시면 됩니다.)

nix-env -iA nixpkgs.direnv

그리고 문서를 참고해서 direnv hook을 추가한 뒤 쉘을 새로 띄웁니다.

프로젝트 디렉토리 하위에 .envrc를 만들고 use nix를 적어줍니다. 최초 한번 direnv allow를 실행해주어야 합니다.

~/myproject$ echo "use nix" > .envrc
direnv: error /home/ditto/myproject/.envrc is blocked. Run `direnv allow` to approve its content

~/myproject$ direnv allow
direnv: loading ~/myproject/.envrc
direnv: using nix
direnv: export +AR +AS +CC +CONFIG_SHELL +CXX +DETERMINISTIC_BUILD +HOST_PATH +IN_NIX_SHELL (...생략)

# 와! nix-shell 안에 있어요
~/myproject$ which node
/nix/store/y9ay04l5mfm255r296vhcjbxjqkjxp39-nodejs-14.16.1/bin/node

# 다른 디렉토리로 빠져나오면 이전 상태로 돌아옵니다
~/myproject$ cd
direnv: unloading
~$ which node
/usr/bin/node

더 알아보기

Diff Monster를 소개합니다

· 약 6분

TL;DR: Diff Monster는 GitHub 풀 리퀘스트 리뷰를 조금 편하게 해주는 웹 기반 도구입니다.

아래 글을 읽기 싫다면 지금 바로 접속해보세요.

스크린샷

어쩌다 이런 걸 만들게 되었나요

  • 기: 연초부터 회사에서 Bitbucket Server를 그만 쓰고 GitHub로 옮기게 되었습니다. 다른건 다 좋은데 코드 리뷰 인터페이스가 너무 불편했습니다.
  • 승: 5월에 긴 연휴가 있어서 한번 코드 리뷰 툴을 만들어보자는 무모한 계획을 세웠습니다.
  • 전: 당연히 연휴 중에 완성 못했고, GitHub API에서 되는게 별로 없어서 꾸역꾸역 개발했습니다.
  • 결: 뭔가 간신히 나오긴 했습니다.

무슨 기능이 있나요

파일 트리

변경된 파일을 디렉토리 계층 구조로 묶어서 볼 수 있습니다.

파일 트리

파일명으로 퍼지 검색이 가능합니다.

퍼지 검색
RIC를 입력하면 RealInterceptorChain.java를 찾아줍니다.

GitHub와 비교: GitHub는 파일 목록이 항상 펼쳐져 있지 않아서 파일 사이를 이동할 때 불편합니다. 심지어 목록을 펼칠 때마다 맨 위부터 다시 파일을 찾아야 합니다. 그리고 그냥 목록으로 나열되어 있어서 보기가 힘듭니다.

파일마다 리뷰 완료 기록

파일마다 리뷰 완료 여부를 표시할 수 있습니다. 큰 PR을 볼 때도 리뷰를 어디까지 했는지 쉽게 알 수 있습니다. (일단 작동은 하지만 좀 더 개선의 여지는 있습니다. 단축키를 추가한다거나.)

파일마다 리뷰 완료 기록

GitHub와 비교: GitHub엔 없는 기능!

리뷰 댓글 작성

GitHub에서 제공하는 기능 중 기본적인 것은 대부분 구현했습니다. 모아서 한번에 올리기도 됩니다. (작성한 댓글은 GitHub에 저장됩니다.)

Commented via Diff Monster
댓글을 달 때 마지막에 작은 서명이 붙으니 놀라지 마세요. :)

GitHub와 비교: 아직 댓글 수정, 답글 달기, 리뷰 취소는 지원하지 않습니다.

승인하기

한번 클릭으로 풀 리퀘스트를 승인(approve)할 수 있습니다.

원 클릭

GitHub와 비교: GitHub에서는 Review changes 클릭 - Approve에 체크 - Submit review 클릭의 세 단계를 거쳐야 합니다. 물론 리뷰 요약을 작성할 수 있도록 이렇게 했겠지만 Approve할 때 사족을 다는 경우는 별로 없다고 생각합니다.

3단계
GitHub은 세 번 클릭해야 한다.

인박스

리뷰해야 할 풀 리퀘스트를 한 곳에서 볼 수 있습니다. 오른쪽 위의 상자 아이콘을 누르면 나옵니다. (로그인 필요)

인박스

GitHub와 비교: GitHub에도 풀 리퀘스트 모아보기 페이지가 있긴 합니다. 근데 리뷰 댓글을 하나라도 달면 거기서 풀 리퀘스트가 사라져 버립니다. (왜 그랬을까?) Diff Monster에서는 Reviewing 탭에 계속 나와요.

앞으로의 계획

처음에 계획했던 기능은 대부분 구현했는데 아직 GitHub에서 제공하는 모든 기능이 되지는 않아서 보충이 필요합니다. 그리고 UI에 자잘하게 개선해야 할 부분이 많이 있습니다.

저희 회사에서 몇몇 분들이 써보시긴 했지만 다른 팀의 워크플로우에는 잘 맞지 않을 수도 있어서 그런 부분도 피드백을 받아 보완해보고 싶은 생각입니다. (물론 이대로 방치될 가능성이 상당히 높습니다 ㅋㅋㅋㅋㅋ)

링크