Kroisse님과는 하스켈 서버에서 같은 주제로 이야기를 나누었는데, 나는 패키지 매니저 그냥 만들지 말자는 입장이다. 또는 작게 만들거나.

패키지 매니저가 하는일이

  1. 조건에 맞는 패키지를 찾아줌
  2. 패키지를 다운받게 해줌

여기서 2를 위해 별도의 프로그램이 필요하진 않다. 그냥 http나 git 클라이언트 쓰면 된다. 애초에 패키지 매니저들도 레지스트리로부터 패키지를 다운받는것외에, http, git 등을 레지스트리에 올리기 이전 개발단계의 편의를 위해 별도로 지원한다.

그럼 1번이 문제인데, 이게 쉬운 문제였으면 정말로 패키지 매니저가 필요없긴 했겠지. 저 조건이란게 단순히 strict한 버전이었다면 git tag등으로 명시하면 그만이다. 현실은 ^3.1.0 같은 여러 버전을 허용하는 방식이고, 같이 설치하는 패키지들의 버전들의 제약 조건을 풀어서 만족하는 버전을 찾아내야한다. 이걸 하려면 여러 패키지들을 모아놓아야하다보니 패키지 레지스트리라고 하는 서버가 생긴다. 그리고 패키지 매니저는 그 서버에 대한 클라이언트가 된다.

... 이렇게 써놓고보니 마치 서버에서 버전 제약 조건을 푸는 solver 역할도 할것 같은데, 대부분의 경우 그렇지 않다. 보통 클라이언트한테 패키지의 메타데이터(어떤 버전이 있는지, 각 버전마다 의존성은 뭔지) 내려주고 클라이언트에서 푼다. 패키지 수가 별로 많지않은 하스켈의 Hackage의 경우엔 그냥 메타데이터들 모아놓은 tar 파일을 하나 내려주는게 끝이다.

패키지 매니저란게 뭔가 거창한거 같은데, 의외로 별거 아닌 동작들을 한군데 모아놓은거란 걸 알수 있다. 확실히 까다로운 부분이라면 버전 solver 정도? 그리고 여기다가 꼭 패키지 매니저가 할 필요는 없는 기능들을 하나둘 넣어서(빌드나 npm run 같은 잡 기능이나) 또 별 이유없이 큰 프로그램을 만든다. 그렇다면 UNIX 철학에 따라 최대한 작은 패키지 매니저를 만들면 어떻게 될까?

그냥 버전 솔버만 만들면 된다는게 내 의견이다. 나머지는 그냥 파일 다운로드 받는거고 git한테 맡기면 된다. 더 나아가 버전 VCS가 버전 솔버까지 해야한다는게 내 입장이지만 이 얘기는 일단 pass. 또 Hackage와 달리 npm의 경우에 그 규모 때문에 패키지 메타데이터를 통째로 받기가 어렵긴 하다. 하지만 많은 언어들이 Hackage같은 접근을 할 수 있고(Rust의 crate.io도 그랬던걸로 안다), 그게 불가능할 경우에도 문제를 해결할만큼만 프로그램을 키우는게 낫다고 본다.

그리고 자꾸 Nix 얘기만 해서 짜증날까봐 걱정이긴한데, 여기서 버전 솔버 빼고 나머지를 모조리 Nix한테 맡길수 있다. 패키지 다운로드, locking, 빌드 등. 이때 패키지 매니저를 최대한 작게, 솔버 역할로만 만들어야지 Nix와 쉽게 연동될 수 있다. Nix가 다른 건 다 포용해줘도, 쓸데없는 IO 많이 발생시키는건 쉽게 안 봐준다. 다른 옵션으로, 만약 Nix를 안 쓰겠다면(합리적인 이유들이 있음), 차라리 Bazel/Buck과 같은 범용 빌드시스템을 위한 해당 언어의 플러그인/rule 같은걸 만드는 것도(이것도 거의 버전 solver에 가까울 거다), 큼지막한 패키지 매니저를 개발하는걸 피함과 동시에, 결과적으로 더 나은 결과를 얻을수 있다.

4

If you have a fediverse account, you can quote this note from your own instance. Search https://hackers.pub/ap/notes/019ce290-5ada-77f1-97b0-179f8cb825ed on your instance and quote it. (Note that quoting is not supported in Mastodon.)