Email me

2026년 10월 24일 자 영어 원문을 번역했습니다. 숫자와 출처는 원문과 같습니다. 영어 원문 읽기 →

개발 · · 11분 분량 · Matt Busel

분류: Rust 가이드

crates.io 다운로드 수: 저희 다운로드의 80%는 새 버전과 함께 들어왔습니다

crates.io 다운로드 수: 저희 다운로드의 80%는 새 버전과 함께 들어왔습니다

요약: 2026년 10월 17일, 제가 가진 Rust 크레이트 69개에 대해 crates.io가 보유한 일별 다운로드 수를 전부 가져왔습니다. 89일 동안 기록된 다운로드는 3,676건이었고, 그중 80.1%가 새 버전이 올라간 당일이나 다음 날에 들어왔습니다. 새 버전은 내용과 상관없이 첫 24시간 동안 약 13건의 다운로드를 모은 뒤 그대로 평평해집니다. 69개 중 하나라도 의존하는 외부 크레이트는 0개였습니다. 사람들이 실제로 크레이트를 쓰는지 알려 주는 숫자는 조용한 날 기준선(quiet-day baseline)이며, 저희 경우 339건, 하루 약 3.8건이었습니다.

검색으로 오신 분을 위한 짧은 답입니다. crates.io 다운로드 수는 크레이트의 .crate 파일이 crates.io CDN에서 몇 번 내려받아졌는지를 CDN 요청 로그로 센 숫자입니다(crates.io는 2024년 3월에 로그 기반 집계로 바꿨습니다). 2025년 10월 29일부터는 cargo에서 온 것으로 보이는 요청(또는 user agent를 아예 보내지 않는 요청)만 집계됩니다. 이 숫자는 사용자 수, 설치 수, 프로젝트 수가 아닙니다. 깨끗한 머신에서 하루 30번 cargo build를 돌리는 개발자 한 명의 CI는 하루 30건을 더하고, 크레이트를 한 번 설치해 로컬 캐시에 계속 두는 사람 한 명은 평생 1건만 더합니다.

그렇다면 작은 크레이트의 숫자 안에는 실제로 무엇이 들어 있을까요? 아래에 실제 포트폴리오를 새로 측정한 결과, 그 데이터를 가져오는 스크립트(복사해서 여러분의 크레이트에 돌려 보세요), 그리고 어느 쪽으로도 자기 자신을 속이지 않고 차트를 읽는 방법을 정리했습니다.

2026년 7월 20일부터 10월 16일까지 Rust 크레이트 69개의 일별 다운로드를 보여 주는 애니메이션 막대 차트. 하루씩 채워지면서 카운터가 3,676까지 올라갑니다. 여름에는 1~3건의 짧은 초록 막대가 이어지고, 배포일인 9월 25일, 26일, 30일과 10월 4일에 높은 초록빛 노란 스파이크가 나타나며, 10월에는 연보라색 스윕 데이가 뒤따릅니다.
크레이트 69개 전체의 일별 다운로드를 날의 종류별로 색칠했습니다. crates.io API, 2026년 10월 17일 오전 7:10 ET 수집. 조용한 날도 보이도록 막대 높이는 제곱근 스케일입니다.

69개의 크레이트는 어디서 왔나

데이터의 모양이 이 크레이트들을 배포한 방식에서 그대로 나오기 때문에 배경부터 설명하겠습니다. 저는 Rust 라이브러리와 도구를 꽤 많이 관리합니다. fin-primitives(트레이딩용 기본 구성 요소), tokio-prompt-orchestrator(중복 제거와 서킷 브레이커가 있는 LLM 프록시), proof-engine(OpenGL 게임 엔진), 그리고 33개 크레이트로 이루어진 워크스페이스로 나뉜 MCP 서버 CoreScout가 있습니다.

배포는 세 번에 몰려서 이루어졌습니다. 2026년 3월에 51개 버전, 9월에 116개, 10월에 68개로, 총 235개 버전입니다. 10월 묶음은 10월 4일 한 번의 대규모 릴리스였습니다. AI 코딩 에이전트가 모든 크레이트를 업그레이드한 뒤, 마지막에 제가 전부 한꺼번에 배포했습니다. 이 하루가 뒤에서 아주 중요해집니다.

10월 17일 오전 7:10 ET에 가져온 누적 합계는 4,815건이었습니다. crates.io의 "recent downloads"(최근 90일) 수치는 3,677이었습니다. 이 크레이트들의 제 목표는 100,000건이므로, 솔직한 질문은 4,815건 중 사람이 얼마나 되느냐입니다.

40줄로 직접 숫자를 가져오기

crates.io에는 공개 JSON API가 있습니다. 공식적으로 버전 관리되지는 않지만 웹사이트 자체가 호출하는 API이며, 데이터 접근 정책이 요구하는 것은 두 가지입니다. 초당 최대 1회 요청, 그리고 누가 요청하는지 밝히는 User-Agent입니다. 엔드포인트 세 개면 모든 정보를 얻을 수 있습니다.

  • /api/v1/crates?user_id=N: 사용자가 소유한 모든 크레이트와 누적 및 90일 합계.
  • /api/v1/crates/<name>/downloads: 최근 90일간의 일별 다운로드를 버전별로 나눈 값(오래된 버전은 extra_downloads로 묶입니다).
  • /api/v1/crates/<name>/reverse_dependencies: 이 크레이트에 의존하는 배포된 크레이트 목록.

아래는 제가 오늘 아침 실행한 스크립트(pull.py, JSON 필드를 골라내는 부분만 잘라냈습니다)입니다. 429를 받으면 재시도하지 않고 바로 멈춥니다. 예의 바른 스크레이퍼는 요청 제한과 다투지 않으니까요.

UA = "tensorust-deepdive-research (contact: hello@tensorust.com)"
last = [0.0]

def get(path):
    wait = 1.05 - (time.time() - last[0])   # stay under 1 request/second
    if wait > 0:
        time.sleep(wait)
    last[0] = time.time()
    req = urllib.request.Request("https://crates.io" + path, headers={"User-Agent": UA})
    try:
        with urllib.request.urlopen(req, timeout=30) as r:
            return json.load(r)
    except urllib.error.HTTPError as e:
        if e.code == 429:
            print("429 - stopping"); sys.exit(2)
        raise

user = get("/api/v1/users/mattbusel")["user"]
crates = get(f"/api/v1/crates?user_id={user['id']}&per_page=100")["crates"]
for c in crates:
    n = c["name"]
    dl = get(f"/api/v1/crates/{n}/downloads")
    vers = get(f"/api/v1/crates/{n}/versions?per_page=100")
    rev = get(f"/api/v1/crates/{n}/reverse_dependencies?per_page=100")
    # ... store dl["version_downloads"], dl["meta"]["extra_downloads"], versions, rev

크레이트 69개에 호출 세 번씩, 초당 한 번이면 약 3분 30초가 걸렸습니다. 그다음 버전 id를 버전 번호와 배포 시각에 매핑하기 위해 69번을 더 호출했습니다. downloads 엔드포인트는 각 행에 "2.15.0" 같은 버전 번호가 아니라 숫자 버전 id를 붙이기 때문입니다.

데이터 수집 과정의 터미널 캡처: 크레이트 69개, fin-primitives 다운로드 561건, 버전 13개, 역의존성 1개, corescout-core 168건, 역의존성 25개, corescout-cli 10, corescout-mcp 11, tokio-prompt-orchestrator 159, every-other-token 162. 이어서 분석 결과: 일별 곡선 13.45, 1.21, 0.02, 0일차와 1일차 중앙값 12, 최솟값 8, 비율 0.869, rev_external은 빈 리스트.
pull.py와 분석 스크립트의 실제 출력, 2026년 10월 17일 오전 7:10~7:16 ET.

크레이트가 수백 개 이상이라면(또는 레지스트리의 모든 크레이트를 보고 싶다면) API를 두드리지 마세요. crates.io는 24시간마다 데이터베이스 덤프(static.crates.io/db-dump.tar.gz)를 공개하며, 여기에 최근 90일간의 일별, 버전별 다운로드 테이블이 들어 있습니다.

crates.io 페이지가 보여 주는 것

아래는 제 크레이트 중 다운로드가 가장 많은 fin-primitives 페이지 하단입니다. 숫자를 읽기 전에 차트부터 보세요. 여름 내내 하루 0~3건의 낮은 물결이 이어지다가, 9월 마지막 주와 10월 첫 주에 높은 스파이크가 솟는데, 스파이크마다 색이 다릅니다. 색 하나가 버전 하나입니다.

fin-primitives의 crates.io 페이지 스크린샷: 최근 다운로드 258건, 누적 다운로드 561건, 배포된 버전 13개, 그리고 90일 누적 다운로드 차트. 여름 동안 하루 0~3건에 머물다가 9월 말과 10월 초에 버전 2.14.0부터 2.15.0까지 배포될 때 약 20, 50, 27로 치솟습니다.
2026년 10월 17일에 캡처한 실제 fin-primitives의 crates.io 페이지. 색이 다른 스파이크 하나가 새 버전 하나입니다.

이 차트는 정직하지만 크레이트 단위입니다. 크레이트가 69개면 차트 69개를 눈으로 훑을 수 없으니, 90일 구간의 모든 크레이트별 하루를 세 가지로 분류했습니다.

다운로드가 일어나는 날의 세 가지 종류

규칙은 단순하고 완전히 기계적입니다.

  1. 배포 구간(publish window): 해당 크레이트가 그 UTC 날짜나 전날에 버전을 배포했습니다.
  2. 스윕 데이(sweep day): 배포는 없었지만, 그날 존재하던 제 크레이트의 절반 이상이 같은 날 다운로드되었습니다.
  3. 조용한 날: 나머지 전부.

analyze.py에 있는 분류기의 핵심 부분입니다.

for n, c in C.items():
    for v in c['downloads']['version_downloads'] + c['downloads']['meta']['extra_downloads']:
        d = dt.date.fromisoformat(v['date'])
        if any(0 <= (d - p).days <= 1 for p in pub[n]):
            cat[v['date']][0] += v['downloads']      # publish window
        elif v['date'] in sweeps:
            cat[v['date']][1] += v['downloads']      # sweep day
        else:
            cat[v['date']][2] += v['downloads']      # quiet

2026년 7월 20일부터 10월 16일까지(UTC 기준 89일, 다운로드 3,676건)의 결과는 다음과 같습니다.

누적 막대와 표: 90일간 다운로드 3,676건. 배포 당일 또는 다음 날: 2,945건, 80.1퍼센트. 스윕 데이, 배포 없이 대부분의 크레이트가 한꺼번에 다운로드된 날: 392건, 10.7퍼센트. 나머지 전부, 조용한 날: 339건, 9.2퍼센트.
크레이트 69개 전체, 2026년 7월 20일~10월 16일(UTC 기준), 이 글의 스크립트로 분류했습니다.

2,945건(80.1%)이 배포 구간에 들어왔습니다. 392건(10.7%)은 여섯 번의 스윕 데이에, 339건(9.2%)은 조용한 날에 들어왔습니다. 하루 최대치는 릴리스를 몰아서 한 10월 4일로, 버전 68개가 배포되었고 다운로드는 1,195건이었습니다.

다르게 말하면, 9월과 10월 버전을 배포하지 않았다면 90일 숫자는 3,676이 아니라 730 언저리였을 겁니다.

새 버전 하나는 약 13건을 받고, 그다음엔 아무것도 없습니다

배포 자체가 얼마의 가치가 있는지 보려고, 구간 안에 배포되어 그 뒤로 최소 일주일치 데이터가 있는 모든 버전(181개)을 골라 배포 후 경과일별로 다운로드를 정렬했습니다.

배포 후 경과일별 새 버전당 평균 다운로드 막대 차트: 0일차 13.45, 1일차 1.21, 2일차 0.02, 3일차 0.13, 4일차 0.57, 5일차 1.15, 6일차 0.27, 7일차 0.07.
2026년 7월 20일~10월 9일에 배포된 버전 181개, 각각 최소 일주일치 데이터 보유. 첫 주 다운로드의 86.9%가 0일차 또는 1일차에 들어옵니다.

0일차 평균 다운로드는 13.45(중앙값 10)입니다. 1일차는 1.21, 2일차는 0.02입니다. 한 버전의 첫 주 다운로드 중 86.9%가 0일차나 1일차에 들어옵니다. 0일차와 1일차를 합친 값은 버전별로 최소 8, 최대 66, 중앙값 12였습니다.

결정적인 단서는 바닥값입니다. 지금까지 배포한 235개 버전 전체에서, 단일 버전의 누적 다운로드 최솟값은 9입니다. 중앙값은 18입니다. 버전이 하나뿐인 크레이트가 19개 있는데, 여기에는 이 프로젝트 밖의 누구도 알 이유가 없는 corescout-cli, corescout-lineage 같은 내부 배관용 크레이트도 포함됩니다. 이들의 누적 합계는 10에서 28 사이이고 중앙값은 15입니다. 사람이 README를 읽든 말든, 무언가가 배포 후 몇 시간 안에 모든 새 버전을 받아 갑니다.

그 무언가가 무엇일까요? 데이터로는 알 수 없습니다. 제 추측은, 어디까지나 추측이지만, crates.io 인덱스를 따라가며 새 버전이 나오는 대로 받아 가는 레지스트리 미러와 빌드 팜, 그리고 보안 및 라이선스 스캐너입니다. 2025년 user agent 필터는 미러를 걸러내려고 만든 것이므로, 그 필터를 통과한 것은 cargo 자체이거나 user agent를 보내지 않는 클라이언트입니다. docs.rs도 새 버전마다 문서를 자동으로 빌드하지만, 그 다운로드가 집계되는지는 공개 문서로 확인할 수 없어서 집계된다고 주장하지는 않겠습니다.

결론은 매우 실용적입니다. crates.io에서는 코드의 어떤 특성보다 배포한 버전 수가 다운로드 수를 더 잘 예측합니다. 제 크레이트 69개에서 버전 수와 누적 다운로드의 상관계수는 0.82입니다. fin-primitives(버전 13개)가 1위이고, 정말로 더 흥미로운 제 크레이트들이 그 뒤에 처지는 이유가 이것입니다.

스윕 데이: 모든 크레이트가 한꺼번에 다운로드되는 날

두 번째 분류가 더 놀라웠습니다. 10월 9일에는 아무것도 배포하지 않았는데 크레이트 69개 전부가 같은 날 다운로드되었고, 합계는 184건이었습니다. 10월 13일에는 69개 중 56개가, 대부분 1건씩 다운로드되었습니다. 이건 사람이 아닙니다. 사람은 도구 하나와 그 의존성 트리를 설치하지, 통계 크레이트, 트레이딩 크레이트, 게임 엔진, TFT 어드바이저를 같은 오후에 설치하지 않습니다.

배포 없이 대부분의 크레이트가 한꺼번에 다운로드된 6일의 격자: 8월 3일, 크레이트 17개 중 17개, 다운로드 17건, 9월 29일, 50개 중 41개, 59건, 10월 5일, 69개 중 58개, 98건, 10월 9일, 69개 중 69개, 184건, 10월 13일, 69개 중 56개, 61건, 10월 15일, 69개 중 37개, 69건.
crates.io 데이터의 스윕 데이. 그날 존재하던 크레이트 하나당 사각형 하나입니다. 이 날들에는 아무것도 배포되지 않았습니다.

구간 안에서 이 패턴에 맞는 날은 6일입니다. 8월 3일(당시 존재하던 크레이트 17개 중 17개), 9월 29일, 10월 5일, 9일, 13일, 15일입니다. 뒤쪽 날짜 일부는 CoreScout 계열로 기웁니다. 10월 6일과 15일에 상위 크레이트는 corescout-core, corescout-mirror, corescout-memory였는데, 무언가가 CoreScout 바이너리의 의존성 트리를 해석했다면 정확히 이렇게 보일 겁니다. 여기서 아무도 말하지 않는 배수 효과가 등장합니다.

워크스페이스는 숫자를 몇 배로 부풀립니다

CoreScout는 Cargo 워크스페이스이고, 워크스페이스를 crates.io에 배포하면 멤버 하나하나가 별도의 크레이트가 됩니다. 아래는 실제 루트 Cargo.toml(발췌)입니다.

corescout-core = { version = "1.2.0", path = "crates/core" }
corescout-mirror = { version = "1.2.0", path = "crates/mirror" }
corescout-substrate = { version = "1.2.0", path = "crates/substrate" }
corescout-memory = { version = "1.2.0", path = "crates/memory" }
corescout-represent = { version = "1.2.0", path = "crates/represent" }
corescout-science = { version = "1.2.0", path = "crates/science" }

corescout-core에는 의존하는 크레이트가 25개 있는데, 전부 같은 워크스페이스의 형제 크레이트입니다. 역의존성 데이터로 보면 corescout-mcp의 의존성 트리 어딘가에 제 다른 크레이트 16개가 들어 있으므로, 깨끗한 머신에서 cargo install corescout-mcp를 한 번 실행하면 크레이트 페이지 17개에 걸쳐 최대 17건의 다운로드로 나타날 것입니다. 69개 크레이트 전체에서 역의존성 API는 의존하는 버전 178개를 보여 주는데, 하나도 빠짐없이 전부 제 것입니다.

이 부분이 잔인합니다. 의존하는 크레이트가 가장 많은 크레이트가 가장 "많이 쓰이는" 것처럼 보이지만(의존 크레이트가 5개 이상인 11개 크레이트의 조용한 날 다운로드 중앙값은 6건, 의존 크레이트가 없는 25개 크레이트는 89일 동안 중앙값 0건), 그건 전부 제가 직접 엮어 놓은 결과입니다.

조용한 날 기준선: 사람을 뜻하는 유일한 숫자

배포 구간과 스윕 데이를 걷어 내면 89일간 339건, 크레이트 69개 전체에서 하루 약 3.8건이 남습니다. "오늘 어딘가에서 누군가가 내 코드로 빌드했다"에 가장 가까운 숫자입니다. 0은 아니고, 계속 늘고 있습니다. 포트폴리오 전체의 조용한 날 다운로드는 7월 말 하루 평균 1.7건, 8월 3.4건, 9월 2.8건, 10월 전반 8.1건이었습니다(10월에는 크레이트 수가 훨씬 많으니 조심해서 보세요).

크레이트 하나가 대부분을 차지합니다. 조용한 날 다운로드 339건 중 128건(38%)이 fin-primitives 하나에서 나왔고, 이번 가을 릴리스 더미보다 훨씬 전인 7월부터 거의 매일 한두 건씩 들어왔습니다. 제 추측으로는 소수의 사람이나 CI 파이프라인 하나가 정기적으로 이 크레이트를 빌드에 쓰고 있습니다. 이건 진짜 신호이고, "배포일 봇일 뿐"이라고 넘겨 버리면 잡음과 함께 바로 이것까지 버리게 됩니다.

그리고 모든 논쟁을 끝내는 숫자가 있습니다. 외부 역의존성은 0입니다. 제 것을 제외한 어떤 배포된 크레이트도 69개 중 하나도 쓰지 않습니다. ecosyste.ms의 crates.io 인덱스는 크레이트를 배포하지 않고 의존만 하는 저장소까지 추적하기 때문에, 이 부분의 좋은 보조 자료가 됩니다.

여러분의 크레이트로 해 보세요

  • 숫자 하나를 숫자 세 개로 읽으세요. 배포 구간, 스윕, 조용한 날입니다. 위 분류기를 돌리거나(아니면 크레이트 페이지에서 버전별 색만 봐도 됩니다), 사용자에 관한 것은 조용한 날 선뿐이라는 점을 기억하세요.
  • 버전 하나당 다운로드 약 10~15건은 공짜로 따라온다고 생각하세요. 갓 나온 크레이트가 첫날 12건을 보여 준다면 아직 아무도 발견하지 않았다는 뜻이고, 그건 괜찮습니다. 3주 뒤 아무 화요일에 12건이 찍힌다면, 아마 누군가 발견한 겁니다.
  • 숫자를 부풀리려고 릴리스하지 마세요. 효과는 있습니다(방금 효과가 있다는 걸 측정했습니다). 바로 그래서 이 숫자를 인기 지표로 믿을 수 없고, 여러분의 크레이트를 평가하는 사람은 다운로드 대신 의존 크레이트와 최근 활동을 볼 겁니다.
  • 다운로드 말고 의존 크레이트를 세세요. crates.io의 Dependents 탭, 역의존성 API, GitHub의 "Used by"가 실제 채택이 드러나는 곳입니다. 다른 사람의 의존성 트리에 들어간 크레이트 하나는 배포일 다운로드 천 건보다 가치가 큽니다. 그 사람의 CI가 돌 때마다 여러분의 크레이트도 영원히 함께 다운로드되기 때문입니다.
  • 워크스페이스는 그 폭만큼 숫자를 부풀린다는 걸 알아 두세요. 도구 하나를 크레이트 30개로 쪼개면 설치 한 번이 다운로드 30건처럼 보입니다. 정직한 대표 숫자를 원한다면 바이너리 크레이트의 숫자를 보고하세요.
  • 정기적으로 다시 가져오세요. API는 크레이트별 일별 데이터를 90일치만 보관합니다. 추세를 보고 싶다면 매달 JSON을 저장하세요. 하루가 구간 밖으로 밀려나면 그날의 일별 분할 데이터는 영영 사라집니다.

숫자 전체

측정 항목(crates.io API, 2026년 10월 17일 오전 7:10 ET 수집)값
크레이트 / 버전69 / 235
누적 다운로드4,815
7월 20일~10월 16일 다운로드(89일)3,676
배포 구간2,945 (80.1%)
스윕 데이392 (10.7%)
조용한 날339 (9.2%), 하루 3.8
새 버전당 0일차 다운로드(평균 / 중앙값)13.45 / 10
첫 주 다운로드 중 0일차 또는 1일차 비율86.9%
단일 버전 누적 다운로드 최솟값9
버전 수와 다운로드의 상관계수0.82
외부 역의존성0

분명히 해 두자면, 이 글은 "다운로드는 가짜다"라는 글이 아닙니다. 집계 규칙은 공개되어 있고 합리적이며, 조용한 날 기준선은 진짜이고 늘고 있습니다. 이 글은 "지금 보고 있는 숫자가 어느 부분인지 알자"는 글입니다. 제가 신경 쓰는 다음 이정표는 다운로드 10,000건이 아니라, 외부 의존 크레이트가 생기는 첫 크레이트입니다. 30일 뒤에 다시 데이터를 가져와 차이를 공개하겠습니다.

크레이트를 관리하고 계신다면, 전체 숫자 옆에 놓인 여러분의 조용한 날 기준선은 어떤가요? 배포 구간 80%가 작은 크레이트에서 흔한 일인지, 아니면 제 릴리스 습관이 상황을 더 나쁘게 만든 건지 정말 궁금합니다.

같은 프로젝트의 다른 글(영어): tokio-prompt-orchestrator 안의 시맨틱 캐시, PC 한 대에서 코딩 에이전트 20개 돌리기(이 크레이트들을 업그레이드한 에이전트들), 639,000 유닛을 다루는 Bevy 인스턴싱.

2026년 10월 17일 tensorust.com에 처음 게시되었습니다. dev.to에도 실렸습니다. 관련 링크: 아무 크레이트나 확인하기: 실제 다운로드와 릴리스일 봇 비교, crates.io의 크레이트 69개 전체, 코딩 에이전트 운영 도구, tokio-prompt-orchestrator의 시맨틱 캐시.

다음 읽을거리

전체 아티클 →

한국어로 더 읽기

한국어: Tensorust →

Get the receipts by email.

What my AI agents tried this week, with the real numbers: what worked, what flopped, what made money. One email when there is something worth reading.

No spam, never sold. Every email has a one-click unsubscribe.

Popular in the shop

All 124 tools →

Browse: Bundles and kitsHome, family and schoolMoney and businessAI toolsSports and fitnessMaking and hobbiesFood and drinkIndie dev and launchTrading and quant

Free: Landing page teardown iPhone app cost calculator LLM API cost calculator Paid online: $49 Launch Check App builds Articles FAQ