Rust 라이브러리를 crates.io에 배포하는 방법
Rust로 라이브러리를 만들었으면 crates.io에 배포해서 다른 사람들이 cargo add로 쓸 수 있게 해야겠죠. 처음 해보면 뭘 준비해야 하는지 헷갈리는데, 생각보다 간단합니다.
1. crates.io 계정 준비
crates.io에 GitHub 계정으로 로그인합니다. 그다음 Account Settings → API Tokens에서 토큰을 생성합니다.
터미널에서 로그인:
cargo login <YOUR_API_TOKEN>
한 번만 하면 됩니다. 토큰이 ~/.cargo/credentials.toml에 저장됩니다.
2. Cargo.toml 필수 필드
crates.io에 publish하려면 Cargo.toml에 최소한 이 필드들이 있어야 합니다:
[package]
name = "my-awesome-lib"
version = "0.1.0"
edition = "2024"
description = "한 줄 설명 (없으면 거부됨)"
license = "MIT OR Apache-2.0"
repository = "https://github.com/username/my-awesome-lib"
| 필드 | 필수 여부 | 설명 |
|---|---|---|
name | 필수 | crate 이름 (crates.io에서 유일해야 함) |
version | 필수 | SemVer 형식 |
edition | 권장 | Rust 에디션 (2021, 2024 등) |
description | 필수 | 없으면 publish 거부됨 |
license | 필수 | SPDX 식별자 (MIT, Apache-2.0, MIT OR Apache-2.0) |
repository | 권장 | GitHub URL |
readme | 선택 | README 파일 경로 (기본: README.md) |
keywords | 선택 | 최대 5개, 검색에 도움 |
categories | 선택 | crates.io 카테고리 |
3. 라이선스 파일
Rust 생태계의 표준은 MIT + Apache 2.0 듀얼 라이선스입니다. 프로젝트 루트에 두 파일을 만듭니다:
LICENSE-MIT— MIT 라이선스 전문LICENSE-APACHE— Apache 2.0 라이선스 전문
Cargo.toml에는:
license = "MIT OR Apache-2.0"
단일 라이선스를 쓰고 싶으면:
license = "MIT"
# 또는
license = "Apache-2.0"
4. README.md
crates.io 페이지에 표시됩니다. 최소한 이 내용은 넣으세요:
# my-awesome-lib
한 줄 설명.
## 설치
\```toml
[dependencies]
my-awesome-lib = "0.1"
\```
## 사용법
\```rust
use my_awesome_lib::something;
fn main() {
// 예제 코드
}
\```
## 라이선스
MIT OR Apache-2.0
5. 배포 전 검증
실제 publish 전에 dry-run으로 확인합니다:
cargo publish --dry-run
이 명령이 하는 것:
- 패키지 압축 (어떤 파일이 포함되는지 확인)
- 압축된 패키지로 빌드 테스트
- 실제 업로드는 하지 않음
문제가 있으면 여기서 에러가 나옵니다.
자주 나는 에러들
error: `description` is missing
→ Cargo.toml에 description 추가
error: `license` is missing
→ Cargo.toml에 license 추가
error: package exceeds maximum size
→ .gitignore나 Cargo.toml의 [package] exclude로 불필요한 파일 제외
6. 실제 배포
cargo publish
끝입니다. 성공하면 이런 메시지가 나옵니다:
Uploading my-awesome-lib v0.1.0
Uploaded my-awesome-lib v0.1.0 to registry `crates-io`
Published my-awesome-lib v0.1.0 at registry `crates-io`
이제 누구나 cargo add my-awesome-lib로 설치할 수 있습니다.
7. 워크스페이스에서 여러 crate 배포
여러 crate가 있는 워크스페이스에서는 의존성 순서대로 배포해야 합니다.
my-core → 의존성 없음 (1번)
my-render → core에 의존 (2번)
my-lib → core + render에 의존 (3번)
my-cli → 전부 의존 (4번)
path + version 병기
로컬에서는 path로 참조하지만, crates.io에서는 version이 필요합니다. 둘 다 적으면 됩니다:
# Before (로컬 전용)
my-core = { path = "../my-core" }
# After (배포 가능)
my-core = { version = "0.1.0", path = "../my-core" }
이렇게 하면:
- 로컬 빌드:
path를 사용 - crates.io에서 다운받은 사용자:
version으로 resolve
배포 순서 실행
cargo publish -p my-core
# 1~2분 대기 (crates.io 인덱스 반영)
cargo publish -p my-render
cargo publish -p my-lib
cargo publish -p my-cli
-p 플래그로 특정 crate만 지정합니다. 각 단계 사이에 약간의 대기 시간이 필요한데, 이전 crate가 crates.io 인덱스에 반영되어야 다음 crate가 의존성을 찾을 수 있기 때문입니다.
Rate Limit 주의
crates.io는 단시간에 너무 많은 crate를 publish하면 429 에러를 반환합니다:
error: Too Many Requests
Please try again after [시간]
5개 이상 연속으로 publish할 때는 사이에 1~2분씩 여유를 두세요.
8. 버전 업데이트
코드를 수정한 후 새 버전을 배포하려면:
Cargo.toml의version을 올린다- 의존하는 다른 crate에서도 version을 맞춘다
cargo publish
# 버그 수정: 0.1.0 → 0.1.1
# 기능 추가: 0.1.0 → 0.2.0
# 호환성 깨짐: 0.1.0 → 1.0.0
version = "0.1.1"
SemVer 규칙:
- patch (0.1.0 → 0.1.1): 버그 수정, 호환성 유지
- minor (0.1.0 → 0.2.0): 기능 추가, 하위 호환
- major (0.x → 1.0): 호환성 깨지는 변경
9. 주의사항
- 한 번 publish한 버전은 삭제할 수 없습니다. yank만 가능합니다 (신규 설치 차단, 기존 사용자는 계속 사용 가능)
- crate 이름은 선점입니다. 먼저 등록한 사람이 소유자
- 민감한 정보 (API 키, .env 등)를 포함하지 마세요. 한 번 올리면 되돌릴 수 없습니다
# 특정 버전 yank (신규 설치 차단)
cargo yank --version 0.1.0
# yank 해제
cargo yank --version 0.1.0 --undo
10. .gitignore / 패키지 제외
publish할 때 불필요한 파일이 포함되지 않도록:
# Cargo.toml
[package]
exclude = ["tests/fixtures/*", "benches/*", ".github/*"]
또는 반대로 포함할 파일만 지정:
[package]
include = ["src/**/*", "Cargo.toml", "LICENSE-*", "README.md"]
체크리스트
배포 전 최종 확인:
-
Cargo.toml에 name, version, description, license, repository 있는지 - LICENSE 파일 존재하는지
- README.md 있는지
-
cargo publish --dry-run통과하는지 - 민감한 정보가 포함되지 않았는지
- 의존하는 crate가 이미 crates.io에 올라가 있는지 (워크스페이스)
- path 의존성에 version이 병기되어 있는지 (워크스페이스)
이것만 확인하면 배포 준비 끝입니다.