mise 런타임 관리자를 통한 환경 대통합

주변에서 한참 동안 잘 써온 도구인데 이상하게 관련된 이야기가 잘 들리지 않아서 영업해 보려 한다. mise다. 구글에 검색할 때는 개발자의 이름을 붙여서 jdx mise라고 검색하면 좋다.

'미즈'라고 읽는다. 나는 그냥 미세라고 한다.

이 글에서는 mise가 필요한 이유 및 대강의 사용법과 함께 mise에 요즘 PR을 날리고 있는 이야기까지 다루려고 한다.

배경

자바 프로젝트 하나를 연다고 해보자. 의존하는 라이브러리들과 그 버전은 빌드 설정에 적혀 있으니 빌드 도구가 자동으로 다운로드해 줄 것이다. 그런데 빌드 도구는 누가 다운로드할 것인가? 자바 실행 환경도 필요한데 이건 직접 설치해야 하나?

옛날에는 sdkman을 쓰는 것이 유일한 해결책이었다. 요즘은 빌드 도구인 그래들이 자동으로 자바까지 설치하는 기능이 생겼다. 어느 쪽이든 간에, 여러 버전의 개발 도구를 동시에 설치해 놓고 프로젝트에 따라 선택해서 쓸 수 있게 하는 것이다. 개발에 필수적인 도구가 아닐 수 없다.

너무나 필수적이었기 때문에 언어마다 이런 도구를 하나씩 만들었다. 노드 생태계 같은 경우 항상 그렇듯이 n개를 만들었다.

asdf의 등장

nvm, pyenv, rbenv, sdkman… 이 모든 도구들이 거의 똑같은 기능을 각자의 코드로 재구현하고 있었다. 각자 쪼개져서 작업하니 도구 자체의 품질도 균일하지 못했고, 사용하는 입장에서는 명령어를 매번 새로 배워야 했다.

n개의 표준을 평정할 단 하나의 표준이 등장해야 했고, asdf가 그것을 해냈다.

asdf: 깃허브 별 21800개

asdf는 배시 스크립트로 플러그인을 만들 수 있게 하여 누구든 자유롭게 원하는 도구를 asdf로 관리할 수 있게 했다.

mise가 미래다

asdf는 많은 사람들에게 사랑받고 있지만, 몇 가지 면에서 개선할 수 있다.

  • 배시 스크립트라 느리다. (훅이 실행될 때마다 120ms까지 걸린다고 함)
  • CLI 경험이 아주 좋지는 못하다.

mise는 asdf의 기능을 유지하면서 러스트로 재구현하고 사용성을 개선했다. 현 시점에서 asdf 대신 mise를 안 쓸 이유는 없다고 생각한다. 자세한 비교는 mise 문서를 참고하면 된다.

mise를 설치한 상태에서 Node.js 20을 사용하기 위해서는 명령어 한 줄이면 충분하다.

mise use -g node@20

현재 디렉터리에서만 Node.js 18을 사용하고 싶다면 아래와 같이 쓴다.

mise use node@18

나처럼 최신 버전을 좋아한다면 mise use -g node@latest 로 설정하고 mise up으로 업데이트해 가면서, 버전 고정이 필요한 프로젝트만 따로 설정해서 쓰면 좋다.

백엔드

mise의 구조 중 흥미로운 부분은 mise가 다양한 백엔드를 지원한다는 것이다.

mise는 기본적으로 asdf의 배시 스크립트 기반 플러그인 생태계를 그대로 지원하지만, 이외에도 다른 여러 가지 백엔드로의 설치를 지원한다. 쓰고 싶은 도구가 asdf에 플러그인이 없더라도 다른 방식으로 설치해서 관리할 수 있는 것이다.

예를 들어 cargo나 go, npm 백엔드 등은 해당 저장소에서 툴을 다운로드해 준다. 러스트와 고는 빌드 도구가 표준화되어 있어 소스로부터 빌드도 쉽게 되기 때문에, 다른 패키지 매니저에서 지원 안 하는 도구를 설치하기 좋다. ubi 백엔드는 깃허브 릴리스에서 직접 다운로드해 준다.

mise use -g cargo:static-web-server@latest

한편, mise 자체는 러스트로 구현되어 있지만 플러그인 생태계가 배시 스크립트를 이용하므로 윈도에서 사용할 수 없는 문제가 있다. 근본적으로 배시 스크립트가 좋은 플러그인 인터페이스는 아니다. 이를 해결하기 위해 vfox의 루아로 된 플러그인 인터페이스도 지원하고 있다.

윈도를 향하여

나는 개발할 때 윈도와 리눅스를 쓴다. 회사 동료들이 모두 맥OS를 쓸 때 혼자 x86-64 윈도와 aarch64 리눅스를 사용함으로서 개발 환경의 다양성을 수호하고 있다.

웹 백엔드 개발자로서 특정한 운영 체제에 종속된 도구는 거의 안 쓰는 데다 각 운영 체제마다 특별한 단점들이 있기 때문에 윈도와 리눅스를 오가면서 개발하는 것이 그렇게 어렵지 않았다.

그러나 윈도에서 런타임 관리할 도구가 없는 건 항상 불편했다. 그렇기 때문에 mise에서 윈도 지원을 시작한다고 해서 당장에 구경하러 갔다.

Windows support: very minimal

셸과 상호 작용을 하는 이런 도구들은 환경마다 신경 쓸 부분이 생기기 때문에 단번에 지원이 추가되기는 어렵다. 윈도에서 mise로 버전 관리를 시작해 보니까 제대로 되는 게 없고 모든 명령이 오류를 냈다.

윈도 빌드가 시작된 것은 2024년 8월, 그리고 9~10월까지 릴리스 노트에 계속 윈도 버그 픽스가 한두 개씩 올라와서 희망이 있다 싶었다. 그리고 이런 것은 누군가 계속 쓰면서 버그를 찾아야 고쳐지는 거니까, 내 환경을 mise로 옮기면서 터지는 부분을 고치는 것을 반복했다.

fix(windows): use join_paths to create new_path by finalchild · Pull Request #2708 · jdx/mise
Fixes the issue that hook_env tries to join paths with ‘:’ on Windows.
fix(windows): escape backslash in nu script & use proper csv by finalchild · Pull Request #2710 · jdx/mise
The mise exe location often includes backslashes in windows, which must be escaped in nushell. Nushell has a csv parser, so we can use this standardized format to pass data. On my setup, "use…
fix: use npm.cmd on windows by finalchild · Pull Request #2711 · jdx/mise
feat: enable deno core plugin on windows & download deno files from deno server by finalchild · Pull Request #2719 · jdx/mise
Made some pathname fixes that make the deno core plugin work on my windows machine. Plus, Replaced GitHub deno download urls to dl.deno.land which the official installation script uses Replaced G…
fix: don’t skip the latest version fetch by finalchild · Pull Request #2720 · jdx/mise
Removed the code that skips the latest version check if the version is already installed. I don't know the exact purpose of the code, so please double-check. The reasoning is this: If latest_v…

5개의 PR을 날린 결과 이제 내가 쓰는 환경+내가 쓰는 도구에 대해서는 잘 동작하게 할 수 있었다. 나는 셸로 누셸(Nushell)을 쓰는데, 윈도 누셸 환경은 이제 잘 동작한다. 빠른 속도로 고치고 있어서 한 달쯤 지나면 다른 환경에서도 문제 없이 쓸 수 있지 않을까 싶다.

이 일이 끝나면 진정한 개발 환경 대통합을 이루게 된다. 특이점이 가까이 있다.