1P by GN⁺ | ★ favorite | 댓글 1개
  • 지난 6개월간 crates.io는 게시된 패키지를 직접 확인하는 소스 코드 뷰어와 GitHub에서 독립된 계정 체계를 도입하고, 보안·표준 라이브러리 대체 안내를 강화함
  • Code 탭은 파일 검색과 구문 강조, 공유 가능한 줄 선택을 지원하며, CDN의 ZIP·JSON 매니페스트와 HTTP 범위 요청으로 API 서버 부하 없이 필요한 파일만 불러옴
  • RFC #3946에 따라 crates.io 고유 사용자 이름 구현을 시작했으며, 사용자 이름 변경과 보안 검토를 거쳐 향후 GitHub 이외의 인증 제공자를 지원할 계획임
  • 프런트엔드를 Ember.js에서 Svelte로 완전히 이전했으며, 검색·역방향 의존성 조회·CDN 캐싱·Git 인덱스 처리도 성능과 안정성을 높이는 쪽으로 개선함
  • RustSec의 유지보수 중단 경고와 std::sync::LazyLock 같은 표준 라이브러리 대체 API를 패키지 페이지에 표시해 의존성 감사와 불필요한 의존성 제거를 지원함

게시된 패키지를 확인하는 소스 코드 뷰어

  • 패키지 페이지의 새 Code에서 게시된 각 버전의 파일을 crates.io 안에서 탐색할 수 있음
    • 연결된 저장소가 아니라 cargo가 의존성을 추가할 때 실제로 내려받는 파일을 보여줌
    • cargo가 생성한 정규화된 Cargo.toml처럼 저장소에는 없는 파일도 확인할 수 있어 의존성 감사가 쉬워짐
  • 뷰어는 파일 트리 검색과 구문 강조, GitHub 방식의 줄 선택을 지원함
    • 줄 번호를 클릭하거나 드래그하면 #L10-L20 형태의 공유 가능한 URL이 생성됨
  • 서버는 게시된 모든 버전에 대해 ZIP 파일과 파일 구성을 기술하는 JSON 매니페스트를 생성함
    • cargo가 사용하는 .crate 파일은 임의 접근을 지원하지 않는 gzip 압축 tarball이므로, 백그라운드 작업에서 탐색 가능한 ZIP으로 다시 패키징함
    • ZIP과 매니페스트는 정적 CDN을 통해 제공됨
    • 프런트엔드는 매니페스트를 먼저 받은 뒤 각 파일을 HTTP 범위 요청으로 필요할 때만 불러옴
    • 소스 탐색이 crates.io API 서버에 사실상 추가 부하를 주지 않으며, 기존 버전도 일괄 처리해 오래된 릴리스까지 지원함
  • 코드 뷰어의 렌더링 라이브러리는 본래 차이점 렌더러이며, 같은 인프라를 활용한 버전 간 비교 뷰어도 개발 중임
    • 완성되면 crates.io에서 게시 버전 두 개 사이의 정확한 변경 사항을 검토할 수 있음

GitHub에서 독립되는 crates.io 계정

  • crates.io 팀은 5월 말 RFC #3946을 승인함
  • 기존에는 GitHub 로그인과 crates.io 신원이 강하게 결합돼 사용자 이름도 GitHub 계정으로 결정됐지만, RFC는 연결된 계정과 독립된 crates.io 고유 사용자 이름을 도입함
  • 이 고유 사용자 이름은 향후 GitHub 이외의 인증 제공자를 통한 로그인을 지원하기 위한 선행 조건임
  • 구현은 시작됐지만 사용자에게 보이는 주요 미완성 기능으로 사용자 이름 변경이 남아 있음
    • 이를 마친 뒤 다른 인증 제공자 로그인에 관한 추가 RFC와 구현을 진행할 예정임
    • 인증과 계정 보안에 직접 영향을 주는 만큼 작고 신중하게 검토된 단계로 천천히 배포함

보안 권고와 표준 라이브러리 대체 안내

  • 기존 Security 탭은 RustSec 데이터베이스의 보안 권고를 보여주며, 이제 RustSec이 유지보수 중단으로 표시한 패키지에는 페이지 상단에 경고 배너도 나타남
    • 배너에서 세부 정보와 가능한 대안을 담은 해당 권고로 이동할 수 있음
  • 표준 라이브러리에 기능이 흡수된 패키지에는 “You might not need this dependency” 배너가 표시됨
    • 예를 들어 lazy_static은 Rust 1.80부터 std::sync::LazyLock으로 대체할 수 있음
    • 의존성 목록에서 대체된 패키지에는 같은 안내를 제공하는 작은 전구 아이콘이 붙음
  • 관련 데이터는 새 rust-lang/std-replacement-data 저장소에서 관리함
    • 표준 라이브러리 대체 항목만 허용함
    • 모든 항목은 안정화된 std, core, alloc API와 해당 Rust 버전을 인용해야 함
    • 항목을 추가하기 전에 패키지 유지보수자에게 알리고 의견을 받을 기간을 제공함
    • 새 항목은 저장소에 제안할 수 있으며, 축적된 데이터는 다른 도구에서도 활용 가능함

Svelte 프런트엔드 이전 완료

  • crates.io 프런트엔드를 Ember.js에서 Svelte로 옮기는 실험이 성공적으로 끝남
    • 새 프런트엔드는 기존 기능과 동등한 수준에 도달함
    • 4월 공개 테스트를 거쳐 5월 초 기본 프런트엔드로 전환됨
    • Ember.js 애플리케이션은 저장소에서 제거됨
  • 기존 디자인과 기능을 그대로 옮긴 일대일 이전이어서 사용자가 변화를 느끼지 않도록 설계함
  • 팀과 기여자는 현대적인 프레임워크를 사용하면서 신규 기여자의 진입 장벽을 낮추고 반복 개발 속도를 높일 수 있게 됐으며, 소스 코드 뷰어가 그 사례임
  • crates.io가 여러 해 동안 사용한 Ember.js와 전환을 지원한 Svelte 양쪽 팀에 감사를 전함

Ferris 오류 페이지

  • crates.io 오류 페이지의 Ferris가 마우스 커서를 눈으로 따라가도록 바뀜
  • 404 오류 페이지에서도 작은 상호작용을 제공함

검색과 역방향 의존성 조회 성능

  • 관련도순 검색은 이전에 검색어와 일치하는 모든 패키지의 순위를 계산해 짧거나 흔한 검색어에서 1~2초가 걸릴 수 있었음
    • 이제 최근 다운로드 수가 가장 많은 일치 패키지 1,000개로 순위 계산 범위를 제한함
  • 역방향 의존성 엔드포인트는 요청마다 전체 의존 패키지 집합을 다시 계산하지 않음
    • 데이터베이스 트리거로 동기화되는 사전 계산 테이블에서 결과를 제공함
    • 비용이 큰 조인을 제한된 인덱스 스캔으로 바꿔 시간 초과 가능성을 크게 낮춤

아키텍처 문서와 Markdown 렌더링

  • ARCHITECTURE.md를 전면 개편해 crates.io의 상위 시스템과 상호 연결 방식을 중심으로 구성함
    • cargo publish 실행 시 발생하는 처리 과정
    • 일반적인 패키지 다운로드가 API 서버를 거치지 않는 이유
    • CDN 접근 로그에서 다운로드 수를 산출하는 방식이 포함됨
  • README는 널리 쓰이는 Markdown 확장인 정의 목록을 렌더링함
    • Markdown 렌더러 comrak은 이미 정의 목록을 지원했지만 해당 확장이 활성화되지 않은 상태였음

CDN 캐시 효율 개선

  • 정적 CDN에 업로드되는 파일에 캐시 태그 메타데이터를 추가함
    • 파일 URL마다 개별 무효화 요청을 보내는 대신 특정 패키지나 릴리스의 모든 캐시 파일을 한 번에 무효화할 수 있음
  • 공개 API 응답과 프런트엔드 자산의 CDN 캐싱을 방해하던 전역 Vary: Cookie 응답 헤더를 제거함
    • 사용자별 응답에는 대신 Cache-Control: no-store를 적용함
    • 그 결과 CDN 엣지의 캐시 적중률이 개선됨

접근성과 Git 인덱스 처리

  • 화면 읽기 도구 사용자를 위해 crates.io의 접근성을 개선함
    • 장식용 아이콘을 접근성 트리에서 숨김
    • 제목 계층을 수정함
    • 목록에 올바른 목록 마크업을 적용함
    • ARIA 스냅샷 테스트를 도입해 회귀가 발견되지 않은 채 반영되는 상황을 방지함
    • 앞으로 몇 달 동안 접근성을 계속 개선할 계획임
  • 백그라운드 워커의 로컬 Git 인덱스 복제본을 베어·얕은 저장소로 변경함
    • 약 25만 개의 체크아웃 파일과 전체 커밋 기록을 디스크에서 제거함
    • 패키지 게시 빈도가 늘어나는 상황에서 처리 성능을 개선함
  • 주기적인 인덱스 스쿼시는 로컬에서 큰 Git pack을 생성하는 대신 GitHub API를 사용함
    • 이전의 로컬 pack 생성 방식은 프로덕션 워커에서 메모리 부족을 일으킨 적이 있음

피드백 채널

댓글과 토론

Lobste.rs 의견들
  • crates.io 계정을 GitHub에서 분리하려는 작업이 진행 중이라 반가움

    • 예전에는 여러 서비스에서 GitHub 계정으로 로그인하는 기능을 선호했지만, 이제는 덜 매력적으로 느껴짐. Tailscale은 OIDC 신원 제공자를 지원하므로 Codeberg와 내 도메인의 WebFinger를 이용해 로그인하도록 설정함
      자체 도메인의 이메일 example@example.com으로 로그인하려면 https://example.com/.well-known/webfingersubjectacct:example@example.com이고 OpenID Connect 발급자 hrefhttps://codeberg.org인 JSON 파일을 둠
      Codeberg 설정에서는 리디렉션 URI가 https://login.tailscale.com/a/oauth_response인 OAuth2 애플리케이션을 만든 뒤, 발급된 Client IDClient Secret을 Tailscale에 입력하면 됨. 앞으로 crates.io도 비슷한 방식을 제공할 듯함
  • 최근 crates.io의 개선 폭이 이렇게 큰 줄 몰랐음. 평소에는 lib.rs부터 찾았지만 곧 습관이 바뀔지도 모르며, 가장 마음에 드는 변화는 Ferris임

    • 이 개선 중 얼마나 많은 부분이 에이전트 도입 덕분인지 궁금함
  • Ferris의 눈 변화는 물리적으로 말이 잘 되지 않음. 검은 눈의 흰 부분은 정반사 하이라이트인데, 마우스 커서가 광원이라면 눈이 커서를 따라가는 표현이라고 하기도 어려움

  • 의존성을 감사할 때는 먼저 ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/~/cargosrc로 심볼릭 링크해 Cargo가 내려받은 파일에 쉽게 접근하도록 함
    감사할 의존성마다 Git 저장소를 복제해 대상 버전을 체크아웃하고, 추적 중인 파일을 로컬에서 삭제한 뒤 rust-analyzer 프로세스에 SIGSTOP을 보냄. 프로젝트의 Cargo.toml에 의존성을 추가하고 cargo fetch를 실행한 다음, 내려받은 $dependency-$version 디렉터리 내용을 복제한 저장소로 복사해 커밋하고 Git 이력 뷰어로 차이를 검토함
    검토를 마치면 Cargo.lock의 의존성·버전·해시 조합을 스크립트로 신뢰할 수 있는 데이터베이스에 저장해 같은 버전을 다시 확인하지 않음. 절차가 복잡해 보여도 대부분 자동화해 둬서 웹 UI보다 효율적이며, Cargo가 명령줄에서 이런 검토 절차를 지원하면 좋겠음. cargo-crev 같은 도구보다 검토 자체를 돕는 플러그인이 있는지도 궁금함

  • 프런트엔드가 매니페스트만 가져온 뒤 각 파일을 HTTP 범위 요청으로 필요할 때 불러오는 구현은 여기에 있으며, 브라우저 내장 DecompressionStream을 사용함