본문으로 건너뛰기
runtly

macOS · Node, Bun, Deno, pnpm, yarn

어느 프로젝트가 지원이 끝난 런타임에서 돌아가고 있습니까?

버전 관리자라면 어느 것이든 지금 어떤 버전을 쓰는지 알려줍니다. runtly는 여기에 더해 어떤 버전이 보안 패치를 받지 못하는지, 어떤 프로젝트가 그 위에 있는지, 그중 무엇에 아직 손이 가는지 알려줍니다.

macOS용 다운로드 — 무료Universal · Apple Silicon 및 Intel · macOS 10.15+

또는 커맨드라인만

$curl -fsSL https://runtly.flatium.com/download | sh
rt audit
$ rt auditruntly audit7 projects, 1 runtime versions examined · data fetched 3 minutes agoactive project, unsupported runtime  node 18.20.4    EOL 502d ago medium      medium CVE-2025-23085 GOAWAY HTTP/2 frames cause memory leak outside heap      https://nodejs.org/en/blog/vulnerability/january-2025-security-releases/      /Users/you/code/billing-worker      /Users/you/code/checkout-api      /Users/you/code/docs-site      and 4 more      4 of 7 committed to in the last 90 days, 4 inherit the global defaultrt install node@18.20.6rt use node@18.20.6  (4 project(s) inherit the default and are fixed by this alone)runtly audit examines the runtime, not your dependency tree. It does not replace `npm audit`.

01문제

버전 관리자는 숫자를 압니다. 위험은 모릅니다.

nvm use와 그 계열 도구가 답하는 질문은 하나뿐입니다. 지금 어떤 버전이 활성 상태인가. 그 질문은 묻는 순간 끝나고, 그 버전이 아직 패치를 받고 있는지에 대해서는 아무 말도 하지 않습니다.

그래서 답은 대개 바깥에서 옵니다. 컴플라이언스 설문지, 고객사의 보안 검토, 프로덕션에서 어떤 Node 버전을 쓰는지 묻는 공급업체 양식. 그때가 되면 목록은 손으로 만들어야 합니다. 저장소를 하나씩 열고, .nvmrc를 하나씩 읽고, 버전을 하나씩 지원 일정과 대조하면서.

runtly는 그 목록을 가지고 있습니다. 어떤 버전이 설치되어 있는지, 어떤 프로젝트가 그 버전으로 해석되는지, 각 프로젝트가 마지막으로 커밋된 때는 언제인지, 공개된 취약점 권고가 각 버전에 대해 무엇이라고 말하는지를 압니다.

02감사

감사

rt audit은 스캔한 모든 프로젝트를 살펴보고 그 뒤에 있는 런타임 버전을 보고합니다.

결과는 먼저 살펴야 할 순서로 정렬됩니다

도구가 실제로 출력하는 라벨을, 출력하는 순서 그대로 적은 것입니다.

  1. 01

    active project, known vulnerability

    최근 90일 안에 커밋된 프로젝트가 공개된 권고가 있는 버전에서 돌아가는 경우.

  2. 02

    active project, unsupported runtime

    지금도 작업 중인 프로젝트가 보안 패치를 더 이상 받지 못하는 버전에서 돌아가는 경우.

  3. 03

    critical vulnerability

    프로젝트의 활성 여부와 무관하게, 머신 어딘가에 있는 critical 등급 권고.

  4. 04

    losing security support soon

    지원 종료가 다가오는 버전. 아직 이전을 계획할 시간이 남아 있을 때.

  5. 05

    dormant project on an old runtime

    90일 이상 손대지 않은 것. 보고는 하지만 기본적으로 접혀 있습니다. 오늘 오후에 고쳐야 할 것은 아닙니다.

모든 권고를 해소하는 가장 작은 업그레이드

권고되는 것은 메이저가 아니라 구체적인 버전입니다. 2025년 1월 권고가 남아 있는 Node 18.20.4라면 그것은 18.20.6이지 "22로 올려라"가 아닙니다. 고객 계약 때문에 Node 18에 묶여 있는 사람은 후자를 실행할 수 없지만, 전자는 오늘 오후에 실행할 수 있습니다.

버전을 고정하지 않고 전역 기본값을 물려받는 프로젝트에 대해서는, runtly가 그 사실을 밝히고 한 번에 전부 고치는 명령 하나를 덧붙입니다.

0이 아닌 코드로 종료하므로, CI에 둘 수 있습니다

rt audit --fail-on=critical은 결과가 기준에 도달하면 실패 종료 코드를 반환합니다. --fail-onhigh, medium, low, eol, never도 받습니다. --json은 읽고 싶은 무엇이든 쓸 수 있도록 보고서 전체를 출력합니다.

$ rt audit --fail-on=eol$ echo $?1

오프라인에서 동작하고, 그 사실을 숨기지 않습니다

권고 데이터는 24시간 캐시되므로 비행기 안에서도 감사가 동작합니다. 모든 보고서는 두 번째 줄에 데이터가 얼마나 오래되었는지 적습니다 — data fetched 3 minutes ago, 또는 9 hours ago.

데이터의 출처

endoflife.date
지원 기간과 지원 종료 일정.
Node.js Security WG
Node.js Security Working Group의 취약점 데이터베이스.
OSV.dev
오픈소스 취약점 데이터베이스.

03해석

해석

runtly는 작업 디렉터리에서 위로 거슬러 올라가며 처음 찾은 답을 씁니다. 규칙은 가까운 쪽이 이긴다는 것입니다. 우선순위가 낮아도 가까운 파일이 우선순위가 높아도 먼 파일을 이기므로, 워크스페이스 구성원이 모노레포 루트를 덮어씁니다. 그 반대가 아닙니다.

한 디렉터리 안에서의 우선순위, 높은 것부터
1.runtlyrcruntly 자신의 파일. rt pin이 씁니다.
2.nvmrc있는 그대로 읽으므로 기존 저장소를 고칠 필요가 없습니다.
3.node-version / .bun-version단일 런타임용 관례.
4.tool-versionsasdf와 mise 프로젝트.
5package.json → packageManagerCorepack의 필드. pnpm과 yarn용.
6package.json → engines범위는 설치된 버전을 기준으로 해석되며, 가장 높은 일치가 이깁니다.

충족할 수 없는 제약은 오류이지, 폴백이 아닙니다

프로젝트가 설치되지 않은 버전을 요구하면 runtly는 멈추고 그렇게 말합니다. PATH에 우연히 올라와 있는 것을 조용히 실행하지 않습니다. 그 조용한 대체가 바로 일주일 뒤 "로컬에서는 되는데 CI에서 깨진다"가 되는 실패입니다.

$ node --versionerror: this directory requires node `20.99.0`, and no installed version satisfies it.  Declared in: /Users/you/code/bad/.nvmrc (.nvmrc)  Install one: rt install node@20.99.0

rt current는 결정한 파일의 이름을 알려줍니다

"왜 내가 잘못된 버전에 있는가"에 대한 답은 경로이고, 도구는 그 경로를 출력합니다.

$ rt current/Users/you/code/mono/packages/web  runtime  version  source  node     18.20.4  /Users/you/code/mono/packages/web/.nvmrc (.nvmrc)

04속도

속도

shim은 node를 호출할 때마다 먼저 실행되므로 비용이 없어야 합니다. hyperfine으로 500회 측정.

node 호출당 추가 비용
exec만 호출하는, 아무것도 하지 않는 Rust 바이너리1.9 ms
runtly의 shim, 해석한 뒤 exec 호출1.9 ms

해석 작업은 공짜입니다. 남는 것은 프로세스를 시작하기 위해 macOS 자체가 요구하는 비용이고, 이것은 아무도 없앨 수 없습니다.

실제 머신 스캔1초 미만에 136개 프로젝트

05

CLI와 GUI 아래에 공유 코어가 하나 있어서, 무엇이 설치되어 있고 무엇이 위험한지에 대해 둘이 어긋날 수 없습니다. 메뉴 막대 항목으로 창을 열지 않고 버전을 바꿀 수 있습니다.

보안

보안

사용 중인 모든 버전, 그 지원 상태, 그리고 그 뒤에 있는 프로젝트.

런타임

런타임

Node, Bun, Deno, pnpm, yarn의 설치된 버전과 업스트림에서 받을 수 있는 버전.

프로젝트

프로젝트

스캔한 각 프로젝트가 무엇으로 해석되는지, 그리고 어떤 파일이 결정했는지.

06한계

하지 않는 일

보안 범위를 부풀려 말하는 것은 아예 말하지 않는 것보다 나쁩니다. 근거 없는 안심을 만들기 때문입니다. 한계는 셋, 그대로 적습니다.

  • 감사하는 것은 런타임이지, 의존성 트리가 아닙니다

    runtly가 보고하는 것은 프로젝트가 돌아가는 Node, Bun, Deno의 버전입니다. node_modules 안의 패키지에 대해서는 아무 말도 하지 않습니다. npm audit을 대체하지 않으며, 이것을 실행하는 것이 그것을 실행하는 것을 대신하지도 않습니다.

  • Bun과 Deno에서 "결과 없음"은 "아무도 그 데이터를 공개하지 않는다"는 뜻입니다

    두 프로젝트 모두 Node에 있는 것과 같은 공개 권고 데이터베이스를 운영하지 않습니다. runtly는 그들의 지원 종료 상태는 보고하고, 깨끗한 보고서가 알 수 없는 것을 암시하지 않도록 이 경고를 스스로 출력합니다.

  • macOS 전용

    Apple Silicon과 Intel, macOS 10.15 이상. Windows 빌드도 Linux 빌드도 없고, 약속하지도 않습니다.

07무료

무료, 그리고 비공개 소스

무료이면서 소스가 공개되지 않은 개발자 도구에는 곧바로 한 가지 의문이 따라붙습니다. 그래서 이 소프트웨어가 실제로 무엇을 하는지 적습니다.

계정 없음, 가입 없음, 라이선스 키 없음
내려받아 쓰면 됩니다. 등록할 것도, 활성화할 것도 없습니다.
텔레메트리 없음, 어떤 종류의 분석도 없음
앱은 당신에 대해서도, 당신의 머신에 대해서도 아무것도 보고하지 않습니다. 한 번도.
shim은 네트워크에 닿지 않습니다
`node`를 호출할 때마다 먼저 실행되는 부분은 네트워크 요청을 전혀 하지 않습니다.
내려받은 파일은 풀기 전에 검증됩니다
모든 런타임은 배포자가 직접 공개한 SHA256과 대조됩니다. 앱 자체는 Apple의 서명과 공증을 받았고, 유니버설 바이너리로 배포됩니다.

이 소프트웨어가 보내는 네트워크 요청 전부

  • nodejs.org/distNode 릴리스 배포
  • api.github.comBun과 Deno 릴리스 메타데이터
  • GitHub release downloadsBun과 Deno 바이너리
  • registry.npmjs.orgpnpm과 yarn
  • endoflife.date지원 일정
  • raw.githubusercontent.com/nodejs/security-wgNode.js 권고 데이터베이스
  • api.osv.dev오픈소스 취약점 데이터

당신이 직접 받으러 갈 바로 그 주소들입니다. 그 밖에는, 어디로도 보내지 않습니다.

08설치

설치

세 가지 경로가 있고, 머신에 올라가는 것이 서로 다릅니다.

앱 내려받기

앱과 커맨드라인

Applications로 끌어다 놓고, 열고, Set up now를 누릅니다. 앱이 shim을 설치하고 셸 설정까지 직접 합니다 — 어느 단계에서도 터미널이 필요 없습니다.

macOS용 다운로드Universal · Apple Silicon 및 Intel · macOS 10.15+

Homebrew

어느 줄을 실행하느냐에 따라 다릅니다

앱과 CLI

$brew install --cask hieuhuynh93/tap/runtly-app

CLI만

$brew install hieuhuynh93/tap/runtly

셸 설치 스크립트

커맨드라인만 — 창이 의미 없는 서버와 CI를 위해

CLI

$curl -fsSL https://runtly.flatium.com/download | sh

CLI와 앱

$curl -fsSL https://runtly.flatium.com/download | RUNTLY_WITH_APP=1 sh

같은 서명된 바이너리를 내려받아, 풀기 전에 공개된 SHA256과 대조하고, runtly setup까지 실행해 줍니다.

실제로 실행되는 스크립트입니다. 먼저 읽어보고 싶다면: https://dl.runtly.flatium.com/install.sh

어느 경로를 택하든 끝 상태는 같습니다. PATH에 ~/.runtly/bin이 올라가고, rt doctor가 초록을 보고합니다.