본문 바로가기

진리는어디에

[Rust] Cargo 이용해 빌드하기

들어가며

이전 포스트에서는 러스트 설치와 Visual Studio Code와 연동하는 방법에 대해 살펴 보았다. 이번 포스트에서는 모든 프로그래밍 언어의 전통적인 첫 단계인 'Hello World'를 출력하는 프로그램을 만들어 보도록 하겠다.

Cargo

우리는 본격적인 'Hello World' 프로젝트에 앞서 Cargo(카고)라는 러스트 패키지 매니저에 대해 살펴 볼 필요가 있다.

카고는 러스트의 빌드 시스템 및 패키지 매니저로써, 프로젝트를 빌드하고, 의존성을 가진 라이브러리를 다운로드 해주며, 라이브러리들을 빌드하는 등 여러가지 직접 관리하기 힘든 많은 일들을 대신 해준다. 물론 장인정신을 가진 분들은 수작업으로 프로젝트의 의존성을 일일이 관리하고 빌드할 수도 있지만 나는 여러분의 정신 건강과 워라밸을 위해 절대 추천하지 않는다. 앞으로 다룰 모든 러스트 관련 포스트에서는 카고를 이용하고 있다고 가정할 예정이다.

카고는 러스트를 설치할 때 번들로 함께 설치 되므로 별로로 설치할 필요는 없다. 여러분이 [Rust] Rust 설치하기 포스트대로 공식 인스톨러를 이용해 러스트를 잘 설치했다면 카고도 설치 되어 있을 것이다. 여러분의 개발 환경에 카고가 제대로 설치 되었는지 확인하기 위해서는 터미널에 아래와 같은 커맨드를 입력해 보도록하자.

$ cargo --version

'cargo 1.62.0 (a748cf5a3 2022-06-08)'와 비슷한 버전 숫자가 보인다면 정상적으로 설치 되었다. 만일 'command not found'와 같은 에러를 보게 된다면 개별적으로 카고를 다시 설치하거나 러스트를 다시 설치하도록 한다.

Hello World 프로젝트 생성하기

이번 섹션에서는 앞에서 살펴 본 카고를 이용하여 기본적인 프로젝트의 뼈대를 생성하는 방법에 대해 살펴 보도록 하겠다.

터미널에서 아래와 같은 커맨드를 입력하여 러스트 프로젝트를 생성하도록 한다. 윈도우, 리눅스 플랫폼 구분 없이 모두 동일하게 적용 가능하다(만일 Visual Studio Code(VSCode)를 설치 했다면 VSCode의 터미널을 이용하면 더 편하다).

$ cargo new hello_rust --bin
 Created binary (application) `hello_rust` package

위 커맨드 중 'cargo new' 는 인자로 지정된 프로젝트(hello_rust)를 생성하는 명령하다. 마지막 인자인 '--bin'은 라이브러리가 아닌 실행 가능한 어플리케이션을 만들도록 한다. 우리는 프로젝트 이름을 hello_rust라고 지정했고 위 커맨드는 아래와 같은 구조의 디렉토리를 자동 생성한다.

위 디렉토리와 파일들에서 주의 깊게 봐야할 부분은 Cargo.toml과 src 디렉토리에 있는 main.rs다. (그외 .gitignore와 같은 다른 파일들도 있는데 지금은 중요하지 않으므로 일단 넘어 가도록 한다)

Cargo.toml

먼저 Cargo.toml에 대해 살펴 보자. Cargo.toml 은 러스트 프로젝트의 환경 설정 파일이다. 앞으로 우리는 이 파일을 이용해 프로젝트를 관리할 것이다. 지금은 Cargo.toml에 대해 중요한 내용을 다루고 있지 않으니 아래 내용들은 가볍게 읽고 지나가도록 하자.

[package]
name = "hello_rust"
version = "0.1.0"
edition = "2021"

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

[dependencies]

첫 번째 섹션 [package]는 어플리케이션의 이름과 버전과 같은 카고가 프로그램을 컴파일하기 위해 필요로 하는 정보를 담고 있다. 

그 다음 섹션 [dependencies]는 여러분의 프로젝트가 가지는 의존성(여러분의 프로젝트가 필요로하는 라이브러리를 dependency, 즉, 의존성이라고 한다)들의 리스트를 적는 섹션이다. 러스트에서는 코드 패키지를 크레이트(crate)라고 한다. 당장은 이 프로젝트를 위한 크레이트는 필요 없으므로 일단 여기까지만 알고 넘어가도록 한다. 다른 보다 복잡한 프로젝트를 다루는 포스트에서 이 섹션을 사용하도록 하겠다.

Tip : TOML은 Tom's Obvious, Minimal Language의 약자다.

src/main.rs

이제 src/main.rs를 열어서 살펴 보도록 하자. 참고로 러스트 코드 파일은 .rs라는 확장자를 가진다.

fn main() {
    println!("Hello, world!");
}

카고는 기본적으로 'Hello, world!'를 출력하는 프로그램을 자동으로 만들어 준다. main.rs 외에도 앞으로 추가되는 모든 코드 파일들은 이 디렉토리 아래에 위치 하도록 한다.

러스트 프로그래밍에 대한 간단한 맛보기로 위 코드를 해부해 보자면 'fn main()'과 같이 fn 키워드와 함께 사용된 것을 '함수'라하고 특히 main 함수는 러스트 프로그램이 실행될 때 프로그램 내에서 가장 먼저 실행되는 특수한 함수다.

그리고 main 함수 내에는 'println!("Hello, world!");' 라는 코드가 있다. println!은 러스트 매크로로써 지정된 문자열을 사용자의 화면에 출력해주는 역할을 한다. 느낌표가 붙어 있는 이것은 매크로라는 것으로써 자세한 사항은 이후에 차차 알아갈 것이다. 지금은 println!은 문자열을 화면에 출력해주는 역할을 한다는것만 기억하고 넘어가도록 하자.

프로젝트 빌드하고 실행하기

cargo build

이제 카고로 만든 hello_rust 프로젝트를 빌드하고 실행 해보도록 하자. hello_rust 디렉토리에서 아래의 커맨드를 입력하면 카고가 자동으로 여러분의 프로젝트를 빌드하여 실행할 수 있는 바이너리 파일을 생성해 줄 것이다.

$ cargo build
   Compiling hello_rust v0.1.0 (D:\hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.71s

이 커맨드는 target/debug 디렉토리 아래에 hello_rust 바이너리 (윈도우라면 hello_rust.ext)파일을 생성 할 것이다.이제 아래 커맨드를 통해 이 실행 파일을 실행해 보도록 하자.

$ ./target/debug/hello_rust  
Hello, world!

만일 모든 것이 우리의 기대대로 진행 되었다면 'Hello, world!'가 출력 된다.

cargo run

앞 섹션에서 우리는 'cargo build'를 이용하여 러스트 프로젝트를 빌드하고 './target/debug/hello_rust'로 이를 실행했지만 'cargo run' 명령어를 이용해 한번의 커맨드로 컴파일과 실행을 동시에할 수 있다.

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

아마도 이번에는 카고가 프로젝트를 컴파일하는 과정을 볼 수 없었을 것이다. 이는 카고가 파일들이 변경된 적이 없음을 감지하고 컴파일 과정을 건너 뛰고 바로 실행 단계로 넘어갔기 때문이다. 만일 여러분이 도중에 코드를 수정했다면 컴파일 관련 내용이 출력 되었을 것이다.

cargo check

'cargo check'는 바이너리를 생성하지 않고 컴파일이 되는지만 빠르게 확인 해주는 커맨드다. 지금은 소규모 프로젝트이기에 빌드에 시간이 오래 걸리지 않지만 프로젝트의 규모가 어느 정도 커지면 러스트의 빌드 속도는 답답하기 그지없다. 이런 경우 컴파일 가능 여부만 테스트하기 위해 'cargo check' 커맨드를 사용한다.

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

릴리즈 버전 빌드

만일 여러분의 프로젝트가 배포를 위한 충분한 준비가 되었다면 'cargo build --release' 커맨드를 이용하여 최적화된 실행 바이너리를 빌드할 수 있다. 이 커맨드는 target/debug 대신 target/release 디렉토리에 실행 파일을 생성한다.

최적화된 바이너리는 여러분의 실행 파일이 보다 나은 성능으로 실행되는 것을 보장하지만, 대신 더 긴 빌드 시간을 필요로 한다. 만일 빌드 과정이 빈번하게 발생하는 개발 중에는 디버그 버전으로 빌드하고, 더 이상 빌드가 필요하지 않고 실행만을 남겨 두고 있는 상황에서는 릴리즈 버전으로 빌드하여 배포하면 된다.

마치며

이상 카고 패키지 & 빌드 매니저를 사용하여 러스트 프로젝트를 생성하고 빌드하는 방법에 대해 살펴보았다. 이번 포스트의 내용을 정리하자면 아래와 같다.

  • cargo build나 cargo check를 사용하여 프로젝트를 빌드할 수 있다.
  • cargo run을 사용하여 빌드와 실행을 동시에할 수 있다.
  • 카고는 실행 바이너리를 ./target/debug 디렉토리에 생성한다.

부록 1. 같이 읽으면 좋은 글

유익한 글이었다면 공감(❤) 버튼 꾹!! 추가 문의 사항은 댓글로!!