[Chapter 7-1] Rust 모듈 - mod와 파일 시스템

hwwwa·2021년 11월 6일
0

🦀 Rust

목록 보기
17/25

모듈을 통한 코드 재사용과 조직화

Rust는 조직화된 방식으로 코드의 재사용을 도와주는 모듈(module)을 갖추고 있습니다. 코드 몇 줄을 함수로 추출하는 것과 같은 방식으로, 함수(혹은 구조체나 열거형 같은 다른 코드들)를 다른 모듈로 뽑아낼 수 있으며 이들을 public 혹은 private으로 정의할 수 있습니다.

  • mod : 새로운 모듈 선언
  • pub : 기본적으로 함수, 타입, 상수, 모듈은 모두 private이기 때문에 pub 키워드를 통해 public 선언
  • use : 모듈이나 모듈 내의 정의들을 스코프 안으로 가져와서 쉽게 참조 가능하도록 함

mod와 파일 시스템

먼저 cargo를 이용해 binary crate를 만드는 대신에 library crate를 만듭니다. library crate란 다른 사람들이 자신들의 프로젝트에 dependency로 추가할 수 있는 프로젝트를 말합니다.

$ cargo new communicator --lib
$ cd communicator

cargo가 src/main.rs 대신 src/lib.rs 를 생성했으며 내부에는 아래와 같은 코드를 찾을 수 있습니다.

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}

cargo는 우리가 만든 라이브러리의 작성 시작을 돕기 위해 빈 테스트를 만드는데, 이는 --bin 옵션을 사용했을 때 "Hello, world!" 바이너리를 만들어준 것과 사뭇 다릅니다.

src/main.rs 파일이 없기 때문에 cargo run 커맨드로 cargo가 실행할 것이 없습니다. 따라서 여기서는 library crate 코드를 컴파일하기 위해 cargo build를 사용할 것입니다.

모듈 정의

communicator 네트워크 라이브러리를 위해 먼저 connect 라는 이름의 함수가 정의되어 있는 network 라는 이름의 모듈을 정의합니다. Rust 내 모듈 정의는 모두 mod로 시작됩니다. 아래의 코드를 src/lib.rs 의 테스트 코드 윗 쪽에 추가합니다.

mod network {
    fn connect() {
    }
}

같은 파일 내에 여러 개의 모듈을 나란히 정의할 수도 있습니다.

mod network {
    fn connect() {
    }
}

mod client {
    fn connect() {
    }
}

모듈 안에 다른 모듈을 집어넣는 것도 가능합니다.

mod network {
    fn connect() {
    }

    mod client {
        fn connect() {
        }
    }
}

모듈을 다른 파일로 옮기기

Filename: src/lib.rs

mod client {
    fn connect() {
    }
}

mod network {
    fn connect() {
    }

    mod server {
        fn connect() {
        }
    }
}

위의 코드에서 client 모듈의 코드를 선언 부분만 남겨둡니다.

mod client;

mod network {
    fn connect() {
    }

    mod server {
        fn connect() {
        }
    }
}

여전히 client 모듈을 선언하고 있지만 코드 블록을 세미콜론으로 대체함으로써 Rust에게 client 모듈의 스코프 내에 정의된 코드를 다른 위치에서 찾으라고 말하게 됩니다. 달리 말하자면 mod client; 의 뜻은 아래와 같습니다.

mod client {
    // contents of client.rs
}

이제 모듈의 이름과 같은 이름을 가지는 외부 파일을 만듭니다.

Filename: src/client.rs

fn connect() {
}

이미 src/lib.rs 안에 client 모듈을 선언했기 때문에 이 파일 안에서 mod 선언이 필요하지 않습니다.

동일한 방식으로 network 모듈을 개별 파일로 추출합니다.

Filename: src/lib.rs

mod client;

mod network;

Filename: src/network.rs

fn connect() {
}

mod server {
    fn connect() {
    }
}

이제 몇몇 컴파일 경고가 생기지만 프로젝트는 성공적으로 컴파일되어야 합니다. cargo run 이 아닌 cargo build 를 이용해야합니다.

서브모듈을 추출하는 것은 위의 방법과 조금 다릅니다.

  1. 부모 모듈의 이름에 해당하는 network라는 이름의 새로운 디렉토리를 만듭니다.
  2. src/network.rs 파일을 이 새로운 network 디렉토리 안으로 옮기고, 파일 이름을 src/network/mod.rs로 변경합니다.
  3. 서브모듈 파일 src/server.rs를 network 디렉토리 안으로 옮깁니다.

이에 대응하는 파일 레이아웃은 아래와 같이 생겼습니다:

├── src
│   ├── client.rs
│   ├── lib.rs
│   └── network
│       ├── mod.rs
│       └── server.rs

Filename: src/network/mod.rs

fn connect() {
}

mod server;

Filename: src/network/server.rs

fn connect() {
}

다시 cargo build 를 실행하면 여전히 경고는 발생하지만 성공적으로 컴파일됩니다.

0개의 댓글