# crates.io 개발 업데이트

> Clean Markdown view of GeekNews topic #31417. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=31417](https://news.hada.io/topic?id=31417)
- GeekNews Markdown: [https://news.hada.io/topic/31417.md](https://news.hada.io/topic/31417.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-07-14T09:22:39+09:00
- Updated: 2026-07-14T09:22:39+09:00
- Original source: [blog.rust-lang.org](https://blog.rust-lang.org/2026/07/13/crates-io-development-update/)
- Points: 1
- Comments: 1

## Topic Body

- 지난 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](https://github.com/rust-lang/rfcs/pull/3946)을 승인함
- 기존에는 GitHub 로그인과 crates.io 신원이 강하게 결합돼 사용자 이름도 GitHub 계정으로 결정됐지만, RFC는 연결된 계정과 독립된 **crates.io 고유 사용자 이름**을 도입함
- 이 고유 사용자 이름은 향후 GitHub 이외의 인증 제공자를 통한 로그인을 지원하기 위한 선행 조건임
- 구현은 시작됐지만 사용자에게 보이는 주요 미완성 기능으로 **사용자 이름 변경**이 남아 있음
  - 이를 마친 뒤 다른 인증 제공자 로그인에 관한 추가 RFC와 구현을 진행할 예정임
  - 인증과 계정 보안에 직접 영향을 주는 만큼 작고 신중하게 검토된 단계로 천천히 배포함

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

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

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

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

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

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

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

### 피드백 채널
- crates.io 관련 의견과 질문은 [Zulip](https://rust-lang.zulipchat.com/#narrow/stream/318791-t-crates-io) 또는 [GitHub Discussions](https://github.com/rust-lang/crates.io/discussions)에서 전달할 수 있음

## Comments



### Comment 61759

- Author: neo
- Created: 2026-07-14T09:22:40+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/posxmd/crates_io_development_update) 
- crates.io 계정을 **GitHub에서 분리**하려는 작업이 진행 중이라 반가움
  - 예전에는 여러 서비스에서 GitHub 계정으로 로그인하는 기능을 선호했지만, 이제는 덜 매력적으로 느껴짐. Tailscale은 **OIDC 신원 제공자**를 지원하므로 Codeberg와 내 도메인의 WebFinger를 이용해 로그인하도록 설정함  
    자체 도메인의 이메일 `example@example.com`으로 로그인하려면 `https://example.com/.well-known/webfinger`에 `subject`가 `acct:example@example.com`이고 OpenID Connect 발급자 `href`가 `https://codeberg.org`인 JSON 파일을 둠  
    Codeberg 설정에서는 리디렉션 URI가 `https://login.tailscale.com/a/oauth_response`인 OAuth2 애플리케이션을 만든 뒤, 발급된 `Client ID`와 `Client 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 범위 요청**으로 필요할 때 불러오는 구현은 [여기](https://github.com/rust-lang/crates.io/pull/14020)에 있으며, 브라우저 내장 `DecompressionStream`을 사용함
  - [DecompressionStream](https://developer.mozilla.org/en-US/docs/Web/API/DecompressionStream)이라는 API를 새로 알게 됨
