Skip to content

1.3. Hello, Cargo


Cargo는 Rust의 빌드 시스템이자 패키지 관리자입니다. 코드 빌드, 코드에 종속된 라이브러리 다운로드, 해당 라이브러리 빌드 등 많은 작업을 Cargo가 대신 처리해 주기 때문에 대부분의 러스티시언은 이 도구를 사용하여 Rust 프로젝트를 관리합니다. (코드에 필요한 종속성(dependencies)을 우리는 라이브러리라고 부릅니다.)

지금까지 작성한 것과 같이 가장 간단한 Rust 프로그램에는 종속성이 없습니다. 만약 Cargo로 "Hello, world!" 프로젝트를 빌드했다면, 코드 빌드를 처리하는 Cargo의 일부만 사용했을 것입니다. 더 복잡한 Rust 프로그램을 작성할수록 종속성을 추가하게 되는데, Cargo를 사용하여 프로젝트를 시작하면 종속성을 추가하는 것이 훨씬 쉬워집니다.

대부분의 Rust 프로젝트가 Cargo를 사용하기 때문에 이 책의 나머지 부분에서는 여러분도 Cargo를 사용한다고 가정합니다. "설치" 섹션에서 설명한 공식 인스톨러를 사용했다면 Cargo는 Rust와 함께 설치되어 있습니다. 다른 방법으로 Rust를 설치한 경우, 터미널에 다음을 입력하여 Cargo가 설치되어 있는지 확인하세요:

cargo --version

버전 번호가 표시되면 설치가 완료된 것입니다. command not found와 같은 오류가 표시되면 설치 방법에 대한 설명서를 참조하여 Cargo를 별도로 설치하는 방법을 알아보세요.

Cargo로 프로젝트 생성하기

Cargo를 사용하여 새 프로젝트를 생성하고 원래 "Hello, world!" 프로젝트와 어떻게 다른지 살펴봅시다. projects 디렉터리(또는 코드를 저장하기로 결정한 위치)로 다시 이동합니다. 그런 다음 모든 운영 체제에서 다음을 실행합니다:

cargo new hello_cargo
cd hello_cargo

첫 번째 명령은 hello_cargo라는 새 디렉터리와 프로젝트를 생성합니다. 프로젝트 이름을 hello_cargo로 지정하면 Cargo가 같은 이름의 디렉터리에 파일을 생성합니다.

hello_cargo 디렉터리로 이동하여 파일을 나열합니다. Cargo가 두 개의 파일과 하나의 디렉터리를 생성한 것을 볼 수 있습니다. Cargo.toml 파일과 main.rs 파일이 있는 src 디렉터리입니다.

또한 .gitignore 파일과 함께 새 Git 리포지토리를 초기화했습니다. 기존 Git 리포지토리 내에서 cargo new를 실행하면 Git 파일이 생성되지 않으므로 cargo new --vcs=git을 사용하여 이 동작을 재정의할 수 있습니다.

Note

Git은 일반적인 버전 관리 시스템입니다. --vcs 플래그를 사용하여 다른 버전 관리 시스템을 사용하거나 버전 관리 시스템을 사용하지 않도록 cargo new를 변경할 수 있습니다. cargo new --help를 실행하면 사용 가능한 옵션을 볼 수 있습니다.

원하는 텍스트 편집기에서 Cargo.toml을 엽니다. 목록 1-2의 코드와 비슷하게 보일 것입니다.

Cargo.toml
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

목록 1-2: Contents of Cargo.toml generated by cargo new

이 파일은 Cargo의 구성 형식인 TOML(Tom's Obvious, Minimal Language) 형식입니다.

첫 번째 줄인 [package]는 다음 문이 패키지를 구성하고 있음을 나타내는 섹션 제목입니다. 이 파일에 더 많은 정보를 추가하면서 다른 섹션을 추가할 것입니다.

다음 세 줄은 Cargo가 프로그램을 컴파일하는 데 필요한 구성 정보, 즉 이름, 버전, 사용할 Rust 에디션을 설정합니다. edition 키에 대해서는 부록 E에서 설명하겠습니다.

마지막 줄인 [dependencies]은 프로젝트의 종속성을 나열할 수 있는 섹션의 시작 부분입니다. Rust에서는 코드 패키지를 크레이트(crates)라고 합니다. 이 프로젝트에는 다른 크레이트가 필요하지 않지만 2장의 첫 번째 프로젝트에서는 필요하므로 그때 이 종속성 섹션을 사용하겠습니다.

이제 src/main.rs를 열고 살펴보세요:

src/main.rs
fn main() {
    println!("Hello, world!");
}

Cargo가 목록 1-1에서 작성한 것과 같은 "Hello, world!" 프로그램을 생성했습니다. 지금까지 우리 프로젝트와 Cargo가 생성한 프로젝트의 차이점은 Cargo는 코드를 src 디렉터리에 배치했고 우리는 최상위 디렉터리에 Cargo.toml 구성 파일을 가지고 있다는 것입니다.

Cargo는 소스 파일이 src 디렉터리에 있을 것으로 예상합니다. 최상위 프로젝트 디렉터리는 README 파일, 라이선스 정보, 설정 파일 및 코드와 관련이 없는 기타 모든 파일을 위한 것입니다. Cargo를 사용하면 프로젝트를 정리하는 데 도움이 됩니다.

"Hello, world!" 프로젝트에서와 같이 Cargo를 사용하지 않는 프로젝트를 시작한 경우 Cargo를 사용하는 프로젝트로 변환할 수 있습니다. 프로젝트 코드를 src 디렉터리로 이동하고 적절한 Cargo.toml 파일을 생성합니다.

Cargo 프로젝트 빌드 및 실행

이제 Cargo로 "Hello, world!" 프로그램을 빌드하고 실행하면 어떤 점이 달라지는지 살펴봅시다! hello_cargo 디렉터리에서 다음 명령을 입력하여 프로젝트를 빌드합니다:

$ cargo build
   Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
    Finished dev [unoptimized + debuginfo] target(s) in 2.85 secs

이 명령은 현재 디렉터리가 아닌 target/debug/hello_cargo(또는 Windows의 경우 target\debug\hello_cargo.exe)에 실행 파일을 생성합니다. 기본 빌드는 디버그 빌드이므로 Cargo는 바이너리를 debug라는 디렉터리에 저장합니다. 이 명령으로 실행 파일을 실행할 수 있습니다:

$ ./target/debug/hello_cargo # or .\target\debug\hello_cargo.exe on Windows
Hello, world!

모든 것이 순조롭게 진행되면 Hello, world!가 터미널에 출력되어야 합니다. cargo build를 처음 실행하면 Cargo가 최상위 레벨에 새 파일을 생성합니다: Cargo.lock이라는 파일을 생성합니다. 이 파일은 프로젝트의 정확한 종속성 버전을 추적합니다. 이 프로젝트에는 종속성이 없으므로 파일 안에 종속성 항목이 없습니다. 이 파일은 수동으로 변경할 필요가 없으며, Cargo가 자동으로 내용을 관리합니다.

방금 cargo build로 프로젝트를 빌드하고 ./target/debug/hello_cargo로 실행했지만, cargo run을 사용하여 코드를 컴파일한 다음 결과 실행 파일을 하나의 명령으로 모두 실행할 수도 있습니다:

$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs
     Running `target/debug/hello_cargo`
Hello, world!

cargo run을 사용하면 cargo build를 실행한 다음 전체 바이너리 경로를 사용하는 것을 기억해야 하는 것보다 편리하기 때문에 대부분의 개발자가 cargo run을 사용합니다.

이번에는 Cargo가 hello_cargo를 컴파일하고 있음을 나타내는 출력이 표시되지 않았습니다. Cargo는 파일이 변경되지 않았다고 판단하여 다시 빌드하지 않고 바이너리를 실행한 것입니다. 소스 코드를 수정했다면 Cargo가 프로젝트를 실행하기 전에 다시 빌드했을 것이고, 이 출력이 표시되었을 것입니다:

$ cargo run
   Compiling hello_cargo v0.1.0 (file:///projects/hello_cargo)
    Finished dev [unoptimized + debuginfo] target(s) in 0.33 secs
     Running `target/debug/hello_cargo`
Hello, world!

Cargo는 cargo check라는 명령도 제공합니다. 이 명령은 코드가 컴파일되기는 하지만 실행 파일을 생성하지는 않는지 빠르게 검사합니다:

$ cargo check
   Checking hello_cargo v0.1.0 (file:///projects/hello_cargo)
    Finished dev [unoptimized + debuginfo] target(s) in 0.32 secs

실행 파일을 원하지 않는 이유는 무엇인가요? 종종 cargo check는 실행 파일을 생성하는 단계를 건너뛰기 때문에 cargo build보다 훨씬 빠릅니다. 코드를 작성하는 동안 작업을 계속 확인해야 하는 경우, cargo check를 사용하면 프로젝트가 컴파일 중인지 알려주는 프로세스가 빨라집니다! 따라서 많은 러스타시언들은 프로그램을 작성할 때 주기적으로 cargo check를 실행하여 컴파일이 완료되었는지 확인합니다. 그런 다음 실행 파일을 사용할 준비가 되면 cargo build를 실행합니다.

지금까지 Cargo에 대해 배운 내용을 요약해 보겠습니다:

  • cargo new를 사용하여 프로젝트를 생성할 수 있습니다.

  • cargo build를 사용하여 프로젝트를 빌드할 수 있습니다.

  • cargo run을 사용하여 프로젝트를 한 번에 빌드하고 실행할 수 있습니다.

  • cargo check를 사용하여 바이너리를 생성하지 않고 프로젝트를 빌드하여 오류를 확인할 수 있습니다.

  • 빌드 결과를 코드와 같은 디렉터리에 저장하는 대신 Cargo는 target/debug 디렉터리에 저장합니다.

Cargo를 사용하면 어떤 운영 체제에서 작업하든 명령어가 동일하다는 추가적인 이점이 있습니다. 따라서 이 시점에서는 더 이상 Linux 및 macOS와 Windows에 대한 구체적인 지침을 제공하지 않겠습니다.

릴리스용 빌드

프로젝트가 마침내 릴리스할 준비가 되면 cargo build --release를 사용하여 최적화를 통해 컴파일할 수 있습니다. 이 명령은 target/debug 대신 target/release에 실행 파일을 생성합니다. 최적화를 사용하면 Rust 코드가 더 빠르게 실행되지만, 이 기능을 켜면 프로그램이 컴파일되는 시간이 길어집니다. 그렇기 때문에 개발용 프로필은 빠르고 자주 재빌드해야 할 때, 다른 프로필은 반복적으로 다시 빌드하지 않고 최대한 빠르게 실행되는 사용자에게 제공할 최종 프로그램을 빌드할 때 사용합니다. 코드의 실행 시간을 벤치마킹하는 경우 cargo build --release를 실행하고 target/release의 실행 파일로 벤치마킹하세요.

관습으로서의 Cargo

간단한 프로젝트의 경우 Cargo는 rustc를 사용하는 것보다 큰 가치를 제공하지 않지만 프로그램이 복잡해지면 큰 가치를 제공할 것입니다. 프로그램이 여러 파일로 커지거나 종속성이 필요한 경우 Cargo가 빌드를 조정하는 것이 훨씬 더 쉽습니다.

hello_cargo 프로젝트는 간단하지만, 앞으로 사용하게 될 실제 도구의 대부분을 사용하고 있습니다. 실제로 기존 프로젝트에서 작업하려면 다음 명령을 사용하여 Git을 사용하여 코드를 체크아웃하고 해당 프로젝트의 디렉터리로 변경한 후 빌드할 수 있습니다:

git clone example.org/someproject
cd someproject
cargo build

Cargo에 대한 자세한 내용은 해당 문서를 참조하세요.

요약

이 장에서는 방법을 배웠습니다:

  • rustup을 사용하여 최신 안정 버전의 Rust 설치하기

  • 최신 Rust 버전으로 업데이트하기

  • 로컬로 설치된 문서 열기

  • rustc를 직접 사용하여 "Hello, world!" 프로그램 작성 및 실행하기

  • Cargo의 규칙을 사용하여 새 프로젝트 생성 및 실행하기

이 단계는 Rust 코드를 읽고 쓰는 데 익숙해지기 위해 보다 실질적인 프로그램을 구축하기에 좋은 단계입니다. 2장에서는 추측 게임 프로그램을 만들어 보겠습니다. Rust에서 일반적인 프로그래밍 개념이 어떻게 작동하는지 먼저 배우고 싶다면 3장을 참조한 다음 2장으로 돌아가세요.


References