패키지와 크레이트

패키지와 크레이트 (Packages and Crates)

모듈 시스템을 배우는 첫 단계로 패키지(package)와 크레이트(crate)를 짚고 넘어갈게요. 크레이트는 러스트 컴파일러가 한 번에 고려하는 가장 작은 코드 단위고, 패키지는 그 크레이트들을 묶어 특정 기능 집합을 제공하는 묶음이에요. 이 둘이 어떤 관계인지, Cargo가 새 프로젝트를 만들 때 실제로 어떤 파일을 만들어 주는지까지 살펴볼게요.

출처: The Rust Book — 패키지와 크레이트

크레이트란 무엇인가

크레이트(crate)는 러스트 컴파일러가 한 번에 고려하는 가장 작은 코드 단위예요. cargo 대신 rustc를 직접 실행해서 단일 소스 코드 파일을 넘긴다 해도(1장의 "Rust Program Basics"에서 우리가 그렇게 했죠), 컴파일러는 그 파일을 하나의 크레이트로 봐요. 크레이트는 모듈을 담을 수 있고, 그 모듈은 크레이트와 함께 컴파일되는 다른 파일에 정의될 수도 있어요. 이 내용은 다음 절들에서 다룰게요.

크레이트는 두 가지 형태 중 하나로 존재해요. 바이너리 크레이트(binary crate)라이브러리 크레이트(library crate) 이죠.

바이너리 크레이트는 실행 가능한 파일로 컴파일해서 실행할 수 있는 프로그램이에요. 명령줄 프로그램이나 서버 같은 것들이죠. 바이너리 크레이트는 각각 실행 파일이 실행될 때 무슨 일이 일어날지 정의하는 main이라는 함수를 반드시 가져야 해요. 지금까지 우리가 만든 크레이트는 전부 바이너리 크레이트였어요.

라이브러리 크레이트는 main 함수가 없고 실행 가능한 파일로 컴파일되지 않아요. 대신 여러 프로젝트와 공유하려는 기능을 정의해요. 예를 들어 2장에서 쓴 rand 크레이트가 무작위 숫자를 생성하는 기능을 제공했던 것처럼요.

러스트 사람들이 "크레이트"라고 말할 때 대부분 라이브러리 크레이트를 뜻해요. 그리고 "크레이트"를 일반적인 프로그래밍 개념인 "라이브러리(library)"와 같은 의미로 쓰기도 해요.

크레이트 루트(crate root) 는 러스트 컴파일러가 시작하는 소스 파일로, 크레이트의 루트 모듈을 구성해요. 모듈에 대해서는 "모듈로 스코프와 비공개 여부 제어하기"에서 자세히 설명할게요.

패키지란 무엇인가

패키지(package) 는 하나 이상의 크레이트를 묶어 특정 기능 집합을 제공하는 묶음이에요. 패키지에는 그 크레이트들을 어떻게 빌드할지 기술하는 Cargo.toml 파일이 들어 있어요. 사실 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 파일이 있어서 패키지가 만들어졌다는 걸 알 수 있어요. src 디렉터리도 있고 그 안에 main.rs가 있어요. 텍스트 편집기로 Cargo.toml을 열어 보면 src/main.rs에 대한 언급이 전혀 없다는 걸 알 수 있어요. Cargo는 관례(convention)를 따르기 때문이에요. src/main.rs는 패키지와 같은 이름을 가진 바이너리 크레이트의 크레이트 루트로 여긴다는 관례 말이죠. 마찬가지로 패키지 디렉터리에 src/lib.rs가 있으면 Cargo는 그 패키지가 같은 이름의 라이브러리 크레이트를 담고 있고, src/lib.rs가 그 크레이트 루트라고 알아요. Cargo는 크레이트 루트 파일들을 rustc에 넘겨서 라이브러리 또는 바이너리를 빌드해요.

여기서는 src/main.rs만 담고 있는 패키지가 있으니, my-project라는 이름의 바이너리 크레이트 하나만 포함하는 거예요. 패키지가 src/main.rssrc/lib.rs를 모두 담고 있으면 크레이트가 두 개예요. 바이너리 하나와 라이브러리 하나인데, 둘 다 패키지와 같은 이름이에요. 파일을 src/bin 디렉터리에 넣으면 바이너리 크레이트를 여러 개 가질 수도 있어요. src/bin 안의 각 파일이 각각 별도의 바이너리 크레이트가 되는 거예요.

더 알아보기 (Learn more)