Rust 모듈 구조

mohadang·2023년 2월 24일
0

Rust

목록 보기
23/30
post-thumbnail

모듈

크레이트 : 실행(bin) 또는 라이브러리(lib) 같은 동작 가능한 코드가 들어있는 바이너리 파일
모듈 : 크레이트 구조화 할 수 있는 하위 구성 단위

모듈 구조화 규칙

최상위에 communicator 모듈이 있고 하위에 client, network 모듈이 있다.

my_mod
 ├── elf_reader
 └── common_reader
     └── file_reader

이를 구성하기 위해서는 다음과 같이 파일 레이아웃을 구성한다.

my_mod
├── src
│   ├── elf_reader.rs
│   ├── lib.rs
│   └── common_reader
│       ├── mod.rs
│       └── file_reader.rs

Rust는 기본적으로 src/lib.rs를 알아서 찾을 수 있다.
만약 다른 mod들이 있다면 src/lib.rs에 기록을 해야 한다.
src/lib.rs는 다른 src/{somthing}.rs 파일들과 다르다

src/lib.rs

/*
아래 코드는 다음과 같다
mod common_reader {
	content of common_reader
}
mod elf_reader {
	content of elf_reader
}
*/
mod common_reader;
mod elf_reader;

src/elf_reader.rs

fn add_two(a: i32) -> i32 {
    // common_reader::internal_adder(a, 2)
    32
}

lib.rs에서 common_reader, elf_reader라는 모듈이 있으며 그 정의는 외부 파일에 기록되어 있다.
모듈은 외부에 다음과 같은 형태의 파일로 존재할 수 있다.
ex) common_reader

  • src/common_reader.rs
  • src/common_reader/mod.rs

이 예에서는 src/common_reader/mod.rs 와 같이 존재하는데 이유는 common_reader 모듈 자체가 file_reader라는 하위 모듈을 가지고 있기 때문이다

src/common_reader/mod.rs

//하위 모듈 있다. 같은 규칙을 적용해서 외부에 file_reader 모듈 정의가 있다.
mod file_reader;

fn internal_adder(a: i32, b: i32) -> i32 {
    a + b
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn internal() {
        assert_eq!(4, internal_adder(2, 2));
    }
}

src/common_reader/file_reader.rs

fn read() {
}

모듈 구조화 규칙은 재귀적으로 적용된다.

lib.rs 한 파일에 적기

굳이 여러 파일과 디렉터리를 사용하여 모듈화 하지 않고 lib.rs에 모두 적을 수 있다.

mod client {
    fn connect() {
    }
}

mod network {
    fn connect() {
    }

    mod server {
        fn connect() {
        }
    }
}

Cargo.toml에 의존성 추가

extern crate elf_reader;

fn main() {
    println!("Hello, world! {}", elf_reader::elf_reader::add_two(10));
}

elf_reader 크레이트를 추가해서 사용하려면 cargo.toml 파일에 의존성을 명시 해주어야 한다.

[package]
name = "file-viewer"
version = "0.1.0"
edition = "2021"

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

[dependencies]
elf_reader = { path = "elf_reader", version = "0.1.0" }

[dependencies] 부분에 elf_reader 의존성을 추가하였다.
저 버전은 = 연산뿐만 아니라 >, <=, ... 등 다른 비교 연산도 가능

모듈 구조를 위한 접근 제한

심플하다. pub 를 통해 공개한다.
단 같은 모듈 파일에 있을 경우 pub는 필요 없다.

mod outermost { // 비공개지만 같은 루트 모듈에 있어 OK
    pub fn middle_function() {} // OK

    fn middle_secret_function() {} // FAIL, pub 필요

    mod inside { // FAIL, pub 필요
        pub fn inner_function() {}

        fn secret_function() {} // FAIL, pub 필요
    }
}

fn main() {
    outermost::middle_function();
    outermost::middle_secret_function();
    outermost::inside::inner_function();
    outermost::inside::secret_function();
}

private 가시성 모듈은 접근이 불가능 하다

mod outermost {
    pub mod inside {
        pub fn inner_function() {
        }
        fn secret_function() {} // FAIL, pub 필요
    }
}
fn main() {
    outermost::inside::inner_function();
    outermost::inside::secret_function();
}

public 메서드에서 private 메서드를 대리 호출하면 호출 가능하다.
inner_function은 secret_function과 함께 같은 루드 모듈인 outermost에 있기 때문이다.

mod outermost {
    pub mod inside {
        pub fn inner_function() {
            secret_function();
        }
        fn secret_function() {} // OK, inner_function으로 호출 가능
    }
}
fn main() {
    outermost::inside::inner_function();
}

use 접근

호출시 경로는 기본적으로 현재 모듈을 기준으로 상대 경로로 해석한다.
other::secret_function 호출시 현재 모듈은 inside이다.

mod outermost {
    mod other {
        pub fn secret_function() {
            println!("call me");
        }
    }
    pub mod inside {
        pub fn inner_function() {
            other::secret_function(); // FAIL
        }
    }
}
fn main() {
    outermost::inside::inner_function();
}

단 하나 예외는 use 구분인데 이는 기본적으로 크레이트 루트에 대한 상대적인 경로로 인식한다.

이 문제를 해결하기 위해서는 상위 모듈로 접근할 수 있는 방법이 필요하다

  • 절대 경로 : crate를 사용하여 루트 모듈에 접근 가능
  • 상위 경로 : super를 사용하여 상위 모듈에 접근 가능
mod outermost {
    mod other {
        pub fn secret_function() {
            println!("call me");
        }
    }
    pub mod inside {
        pub fn inner_function() {
            crate::outermost::other::secret_function();
            super::other::secret_function();
        }
        pub mod deep_inside {
            pub fn deep_inner_function() {
                crate::outermost::other::secret_function();
                super::super::other::secret_function();
            }
        }
    }
}
fn main() {
    outermost::inside::inner_function();
    outermost::inside::deep_inside::deep_inner_function();
}
profile
mohadang

0개의 댓글