패키지와 크레이트
모듈 시스템에서 가장 먼저 다룰 부분은 패키지와 크레이트입니다.
크레이트(crate) 는 러스트 컴파일러가 한 번에 고려하는 코드의 최소 단위입니다.
cargo 대신 rustc 를 실행하고, 소스 코드 파일 하나만 넘긴다고 해도(1장의
“Rust 프로그램의 기초” 절에서 실제로 그랬습니다),
컴파일러는 그 파일을 하나의 크레이트로 취급합니다. 크레이트는 모듈을 포함할 수 있고,
앞으로 보겠지만 그 모듈들은 크레이트와 함께 컴파일되는 다른 파일에 정의될 수도
있습니다.
크레이트는 두 형태 중 하나일 수 있습니다. 바이너리 크레이트 또는 라이브러리
크레이트입니다. 바이너리 크레이트(binary crates) 는 컴파일해 실행 가능한 파일로
만들 수 있는 프로그램입니다. 예를 들어 커맨드라인 프로그램이나 서버가 여기에
해당합니다. 각각은 실행 파일이 돌아갈 때 어떤 일이 일어나는지 정의하는 main
함수를 반드시 가져야 합니다. 지금까지 우리가 만든 크레이트는 모두 바이너리
크레이트였습니다.
라이브러리 크레이트(library crates) 는 main 함수가 없고, 실행 파일로
컴파일되지도 않습니다. 대신 여러 프로젝트가 공유해서 사용할 기능을 정의합니다.
예를 들어 2장에서 사용한 rand 크레이트는 난수를 생성하는
기능을 제공합니다. Rustacean이 “crate” 라고 말할 때는 대부분 라이브러리 크레이트를
의미하며, 일반적인 프로그래밍 개념의 “라이브러리” 와 사실상 같은 뜻으로 쓰기도
합니다.
크레이트 루트(crate root) 는 러스트 컴파일러가 출발점으로 삼는 소스 파일이며, 해당 크레이트의 루트 모듈이 됩니다(모듈은 [“모듈로 스코프와 공개 범위 제어하기”] modules 절에서 자세히 설명합니다).
패키지(package) 는 하나 이상의 크레이트를 묶어 특정 기능 집합을 제공하는 단위입니다. 패키지는 그 크레이트들을 어떻게 빌드할지 설명하는 Cargo.toml 파일을 포함합니다. Cargo 자체도 사실 하나의 패키지입니다. 여러분이 코드를 빌드할 때 써 온 커맨드라인 도구용 바이너리 크레이트를 포함하고 있기 때문입니다. Cargo 패키지는 또한 그 바이너리 크레이트가 의존하는 라이브러리 크레이트도 포함하고 있습니다. 다른 프로젝트는 Cargo 라이브러리 크레이트에 의존해, Cargo 커맨드라인 도구가 사용하는 것과 같은 로직을 재사용할 수 있습니다.
패키지는 원하는 만큼 많은 바이너리 크레이트를 포함할 수 있지만, 라이브러리 크레이트는 최대 하나까지만 포함할 수 있습니다. 또한 패키지는 라이브러리든 바이너리든 적어도 하나의 크레이트는 반드시 포함해야 합니다.
패키지를 만들면 실제로 어떤 일이 일어나는지 살펴봅시다. 먼저 cargo new my-project
명령을 실행합니다.
$ cargo new my-project
Created binary (application) `my-project` package
$ ls my-project
Cargo.toml
src
$ ls my-project/src
main.rs
cargo new my-project 를 실행한 뒤 ls 로 Cargo가 무엇을 만들었는지 확인합니다.
my-project 디렉터리 안에는 Cargo.toml 파일이 있는데, 이것이 패키지를
정의합니다. 또한 main.rs 를 담고 있는 src 디렉터리도 있습니다.
Cargo.toml 을 에디터로 열어 보면, 그 안에 src/main.rs 에 대한 언급은 없습니다.
Cargo는 src/main.rs 가 패키지와 같은 이름의 바이너리 크레이트 루트라는 관례를
따릅니다. 마찬가지로 패키지 디렉터리에 src/lib.rs 가 있으면, 패키지는 패키지와
같은 이름의 라이브러리 크레이트를 포함하고 있고, src/lib.rs 가 그 크레이트의
루트라고 Cargo는 압니다. Cargo는 이런 크레이트 루트 파일들을 rustc 에 넘겨
라이브러리나 바이너리를 빌드합니다.
여기서는 패키지 안에 src/main.rs 만 있으므로, my-project 라는 이름의 바이너리
크레이트 하나만 포함합니다. 만약 패키지에 src/main.rs 와 src/lib.rs 가 모두
있다면, 같은 이름을 가진 바이너리와 라이브러리, 두 개의 크레이트를 포함하게 됩니다.
또한 src/bin 디렉터리에 파일을 넣으면 패키지는 여러 개의 바이너리 크레이트를
가질 수 있으며, 각 파일은 각각 별도의 바이너리 크레이트가 됩니다.