mise-en-place 완벽 가이드 — nvm·pyenv·asdf를 대체하는 Rust 기반 런타임 매니저

mise-en-place 완벽 가이드 — nvm·pyenv·asdf를 대체하는 Rust 기반 런타임 매니저

이 글의 핵심

mise-en-place(구 rtx)는 nvm·pyenv·rbenv·jenv·tfenv·asdf를 모두 대체하는 Rust 기반 통합 런타임·툴 버전 매니저입니다. `.tool-versions` 또는 `mise.toml` 한 파일로 프로젝트마다 Node·Python·Go·Ruby·Java·Terraform·kubectl 등을 고정하고, 디렉터리 진입 시 자동 활성화합니다. 이 글은 설치·사용·tasks 러너·환경 변수 관리·CI 통합을 실전 중심으로 다룹니다.

설치

macOS / Linux

curl https://mise.run | sh
echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc   # zsh/fish 각각
# 또는 brew
brew install mise

exec $SHELL -l
mise --version

Windows

winget install jdx.mise
# PowerShell
mise --version

첫 사용: Node + Python 설치

mise use --global node@20
mise use --global [email protected]

node -v    # v20.x
python -V  # 3.12.x
  • --global: 시스템 전체 기본값
  • 프로젝트에서 오버라이드는 .mise.toml

프로젝트 설정: mise.toml

# mise.toml (프로젝트 루트)
[tools]
node = "20"
python = "3.12"
pnpm = "9"
go = "1.22"
terraform = "1.9"
kubectl = "1.30"
helm = "3.14"

[env]
NODE_ENV = "development"
DATABASE_URL = "postgres://localhost/myapp"

[tasks.dev]
run = "pnpm dev"

[tasks.build]
depends = ["lint", "test"]
run = "pnpm build"

[tasks.test]
run = "pnpm test"

[tasks.lint]
run = ["pnpm lint", "pnpm typecheck"]

디렉터리 진입만으로:

  • 지정된 런타임 자동 활성화
  • 환경 변수 자동 설정
  • mise run dev로 tasks 실행

asdf .tool-versions 호환

node 20.11.0
python 3.12.1
ruby 3.3.0

기존 asdf 프로젝트를 한 줄도 바꾸지 않고 mise로 사용 가능. 점진 이주가 쉽습니다.

도구 설치

mise install              # 현재 디렉터리의 mise.toml/.tool-versions 전부 설치
mise install node@20
mise install node@latest
mise install --jobs=8     # 병렬 설치

Node LTS 별칭

mise use node@lts         # 가장 최신 LTS
mise use node@lts-iron    # LTS 코드네임
mise ls-remote node       # 설치 가능한 버전 목록

활성화 전략

mise는 디렉터리 변경 감지 + 셸 훅으로 동작합니다.

cd ~/projects/app-a   # node 20, python 3.12
node -v               # 20.x

cd ~/projects/app-b   # node 18, python 3.11
node -v               # 18.x
  • mise activate.mise.toml·.tool-versions를 탐색
  • 느린 호출은 거의 없음 (Rust + 캐시)

Tasks Runner

[tasks.ci]
run = [
  "mise install",
  "pnpm install --frozen-lockfile",
  "pnpm lint",
  "pnpm test",
  "pnpm build",
]

[tasks.seed]
description = "DB 시드 데이터 로드"
run = "pnpm tsx scripts/seed.ts"
sources = ["scripts/seed.ts", "prisma/schema.prisma"]
outputs = ["seed.lock"]

[tasks.serve]
wait_for = ["seed"]
run = "pnpm dev"
  • depends: 의존 관계
  • wait_for: 병렬 실행 + 완료 대기
  • sources/outputs: make처럼 변경 감지로 불필요 실행 스킵
mise run ci
mise run serve
mise tasks           # 전체 목록

별도 package.json scripts·Makefile·justfile 없이 모노레포 전체 tasks를 하나로 통합.

환경 변수 / Secrets

[env]
NODE_ENV = "development"
APP_PORT = "3000"

# .env 파일 로드
_.file = ".env.local"

# 1Password CLI
OPENAI_API_KEY = { op = "op://Dev/OpenAI/api_key" }

# AWS SSM
SECRET = { ssm = "/prod/db/password" }

# 동적 (셸 명령 결과)
GIT_BRANCH = { run = "git branch --show-current" }

direnv와 겹치는 영역을 mise가 흡수해 도구 수를 줄일 수 있습니다.

플러그인 / 백엔드

mise는 여러 백엔드(backend)를 지원:

  • core: node·python·ruby·go·java·deno·bun·erlang 등 네이티브 구현
  • asdf: 기존 asdf 플러그인 전부
  • aqua: 수천 개 CLI 도구 (aquaproj.github.io)
  • ubi: GitHub Release 바이너리 자동 설치
  • npm: npm 글로벌 패키지
  • cargo: Rust 크레이트
  • pipx: Python 도구
  • go: go install
mise use aqua:hashicorp/[email protected]
mise use npm:prettier@3
mise use cargo:ripgrep@latest
mise use ubi:BurntSushi/ripgrep

실전 예시: 멀티 언어 모노레포

repo/
  mise.toml                 # 루트 공통 (node, python, go, terraform)
  apps/
    web/.mise.toml          # node 20.11, pnpm 9.5
    api/.mise.toml          # python 3.12
    worker/.mise.toml       # go 1.22
  infra/.mise.toml          # terraform 1.9, kubectl 1.30

각 디렉터리 진입 시 해당 도구 버전으로 전환되어 git worktree·여러 터미널·VS Code 다중 워크스페이스 모두 자연스럽게.

CI 통합

GitHub Actions

- uses: jdx/mise-action@v2
  with:
    install: true
    cache: true
- run: mise run ci

mise.toml[tools] + [tasks.ci]가 그대로 CI에서 실행. 로컬과 CI가 bit-exact 동일.

GitLab CI

image: jdxcode/mise:latest
before_script:
  - mise install
script:
  - mise run test
  - mise run build

셸 성능 최적화

# ~/.config/mise/config.toml (글로벌)
[settings]
experimental = true
idiomatic_version_file_enable_tools = ["node", "python"]
legacy_version_file = true
  • idiomatic_version_file: .nvmrc·.python-version 같은 파일도 인식
  • jobs: 병렬 설치 수
  • raw: 원시 셸 동작 (성능 한계)

Node 전용 기능

[tools]
node = "20"

[env]
_.path = ["./node_modules/.bin"]   # 자동 PATH 추가
  • corepack 활성: mise settings set node.cache_dir...
  • pnpm·yarn·bun은 독립 도구로 관리

업데이트·관리

mise self-update
mise upgrade                # 모든 툴 최신으로
mise outdated               # 업데이트 가능 목록

mise prune                  # 미사용 버전 제거
mise cache clear            # 캐시 정리

트러블슈팅

command not found: node

  • mise activate가 셸 rc에 설정됐는지
  • exec $SHELL -l로 셸 재시작
  • mise doctor로 진단

PATH에 다른 버전이 먼저 있음

  • /usr/local/bin/node·brew node 등 → 제거 또는 PATH 순서 조정
  • mise which node로 어느 경로가 사용 중인지 확인

설치 속도 느림

  • 기본 jobs 4 → mise settings set jobs 8
  • 미리 컴파일된 바이너리 소스 활성 (mise settings set node.install_strategy precompiled)

Python 빌드 실패

  • macOS: xcode-select --install, openssl/xz 등 brew 설치 필요
  • Linux: libffi-dev, libsqlite3-dev

레거시 .nvmrc와 충돌

  • mise는 기본적으로 .tool-versions·.mise.toml 우선
  • idiomatic_version_file_enable_toolsnode 추가 시 .nvmrc 인식

비교 요약

도구언어 범위속도설정 파일
nvmNode느림.nvmrc
fnmNode빠름.node-version
VoltaNode + JS tools빠름package.json
pyenvPython보통.python-version
asdf다수느림.tool-versions
mise다수 + CLI 도구매우 빠름.mise.toml

체크리스트

  • mise 설치 + 셸 활성화
  • 팀 프로젝트에 mise.toml 커밋
  • .tool-versions가 있다면 mise로 이주 또는 호환 유지
  • Tasks runner로 scripts 통합
  • 환경 변수·secrets을 [env]로 관리
  • CI에 jdx/mise-action 적용
  • 주기 mise prune + self-update
  • Node·Python·Terraform·kubectl 등 팀 표준 도구 일괄 관리

마무리

mise는 “도구마다 다른 버전 매니저를 쓰는” 오래된 불편을 Rust 성능과 asdf 호환성으로 단번에 해결한 도구입니다. 설정은 mise.toml 하나로 통일되고, 셸 활성화는 빠르며, CI에서도 같은 환경이 재현됩니다. 2026년 현재 주요 OSS·스타트업이 asdf를 대체하며 사실상 새 표준으로 정착 중이고, Nix의 무거움과 asdf의 느림 사이에서 “실용적 최선”을 찾는 팀에게 최적입니다. nvm·pyenv·rbenv·jenv·tfenv 중 둘 이상을 쓰고 있다면 오늘 바로 mise로 통합해 개발 환경을 단순화하는 것을 강력히 권장합니다.

관련 글

  • Nix & NixOS 완벽 가이드
  • asdf 완벽 가이드
  • dotfiles 관리 가이드
  • devenv 완벽 가이드