3 분 소요

요약

Rust 입문 단계를 지나면 문법보다 먼저 막히는 지점이 프로젝트 구조다. Cargo.toml, src/main.rs, src/lib.rs, mod, use, pub가 각각 무엇을 담당하는지 분리해서 이해하지 못하면, 코드가 조금만 커져도 파일을 어디에 둘지부터 헷갈리기 쉽다.

이 글은 package와 crate의 관계, binary crate와 library crate의 차이, 그리고 main.rs, lib.rs, mod, use, pub를 한 번에 연결하는 데 초점을 둔다. 결론부터 말하면 초급 단계에서는 “Cargo package 하나 안에 실행 진입점은 main.rs, 재사용 로직은 lib.rs, 외부에 보여 줄 것만 pub“이라는 기준을 먼저 잡아 두는 편이 가장 실용적이다.

문서 정보

  • 작성일: 2026-04-15
  • 검증 기준일: 2026-04-16
  • 문서 성격: tutorial
  • 테스트 환경: Windows 11 Pro, Windows PowerShell, Cargo CLI 예시
  • 테스트 버전: rustc 1.94.0, cargo 1.94.0
  • 출처 등급: 공식 문서만 사용했다.
  • 비고: 이 글은 단일 Cargo package 기준의 기본 구조 감각에 집중하며, workspace나 feature 같은 확장 주제는 의도적으로 범위에서 제외한다.

문제 정의

Rust 07에서 module 문법을 보고 나면 초급자는 곧바로 아래 지점에서 멈추기 쉽다.

  • packagecrate가 같은 말인지 다른 말인지 헷갈린다.
  • src/main.rssrc/lib.rs를 언제 함께 두는지 감이 안 잡힌다.
  • 파일을 나눌 때 mod, use, pub를 어떤 순서로 써야 하는지 모호하다.

이번 글은 위 혼란을 줄이는 범위까지만 다룬다. workspace, feature, publish, path dependency처럼 운영 범위가 넓어지는 주제는 일부러 넣지 않고, 하나의 Cargo 프로젝트를 읽고 나누는 기본 감각에 집중한다.

확인된 사실

가장 이해하기 쉬운 기본 구조는 아래처럼 보는 것이다.

rust-layout-demo/
  Cargo.toml
  src/
    main.rs
    lib.rs
    math.rs

이 구조에서 읽는 순서는 아래처럼 잡아 두면 편하다.

  1. Cargo.toml: package 이름과 의존성을 본다.
  2. src/main.rs: 실행이 어디서 시작되는지 본다.
  3. src/lib.rs: 재사용할 모듈을 crate 바깥에 어떻게 공개하는지 본다.
  4. src/math.rs: 실제 기능 코드가 어디에 들어 있는지 본다.

예를 들어 lib.rs에서 모듈을 공개하는 코드는 아래처럼 둘 수 있다.

pub mod math;

math.rs는 재사용할 함수를 담는다.

pub fn add(left: i32, right: i32) -> i32 {
    left + right
}

pub fn subtract(left: i32, right: i32) -> i32 {
    left - right
}

main.rs는 library crate에 공개된 모듈을 사용해 실행 흐름만 조립한다.

use rust_layout_demo::math;

fn main() {
    let sum = math::add(10, 20);
    let diff = math::subtract(20, 5);

    println!("sum = {}", sum);
    println!("diff = {}", diff);
}

초급 단계에서 중요한 포인트는 “실행은 main.rs에서 시작하지만, 실제 로직은 lib.rs와 하위 모듈로 옮길 수 있다”는 점이다. 이 패턴을 먼저 익혀 두면 이후 testing, file I/O, CLI, mini project 글에서도 같은 구조를 반복해서 재사용할 수 있다.

직접 확인한 결과

  • 직접 확인한 결과: 현재 작성 환경에서 Rust toolchain 버전은 아래와 같았다.
rustc --version
cargo --version
  • 관찰된 결과:
rustc 1.94.0 (4a4ef493e 2026-03-02)
cargo 1.94.0 (85eff7c80 2026-01-15)
  • 직접 확인한 결과: 본문과 같은 구조의 임시 Cargo 프로젝트에서 main.rs 예제를 실행했을 때 출력은 아래와 같았다.
cargo run
  • 관찰된 결과:
sum = 30
diff = 15
  • 직접 확인 범위의 한계: 본문 구조를 기준으로 임시 Cargo 프로젝트를 만들어 대표 예제는 실행했지만, 이 저장소 안에 별도 예제 프로젝트를 추가하지는 않았다.

해석 / 의견

  • 내 판단으로는 초급자가 가장 먼저 가져가야 할 감각은 “package는 Cargo가 관리하는 묶음이고, crate는 컴파일 단위”라는 구분이다.
  • 의견: 처음부터 모든 함수를 main.rs에 넣기보다, 재사용할 가능성이 보이는 함수는 빠르게 lib.rs 아래 모듈로 옮기는 편이 테스트 작성과 파일 분리에 유리하다.
  • 의견: pub는 편의 기능이 아니라 API 경계다. 밖에서 써야 하는 항목만 공개하고, 나머지는 기본 비공개로 두는 습관이 유지보수에 도움이 된다.

한계와 예외

  • 이 글은 single package 기준 설명이며, 여러 package를 묶는 Cargo workspace는 다루지 않았다.
  • pub(crate), super, 중첩 모듈 폴더 구조 같은 세부 공개 범위 규칙은 범위에서 제외했다.
  • library crate가 없어도 Rust 프로그램은 만들 수 있다. 다만 파일이 커질수록 lib.rs 분리 패턴이 더 유리한 경우가 많다.
  • package 이름에 하이픈이 있으면 코드에서 crate 이름은 언더스코어로 바뀌는 등 세부 규칙이 추가되는데, 이번 글에서는 가장 단순한 구조만 예제로 사용했다.

참고자료

댓글남기기