코드를 모듈로 분할

완료됨

모듈은 코드를 더 효과적으로 구성하는 데 도움이 되는 것 외에도 값, 형식, 메서드에 대한 프라이버시를 보장합니다.

간소화된 인증 API를 모델링하는 이 예제를 살펴보겠습니다.

mod authentication {
    pub struct User {
        username: String,
        password_hash: u64,
    }

    impl User {
        pub fn new(username: &str, password: &str) -> User {
            User {
                username: username.to_string(),
                password_hash: hash_password(password),
            }
        }    
    }
    fn hash_password(input: &str) -> u64 { /*...*/ }
}

fn main() {

    let user = authentication::User::new("jeremy", "super-secret");

    println!("The username is: {}", user.username);
    println!("The password is: {}", user.password_hash);

}

위의 코드에서는 authentication 모듈이 User 구조체를 User::new 메서드와 함께 제공한다는 것을 알 수 있습니다. 둘 다 퍼블릭이기 때문입니다. pub 키워드를 확인하세요.

이 코드는 User 구조체의 usernamepassword_hash 필드에 액세스하려고 하지만 프라이빗이기 때문에 컴파일되지 않습니다. 코드를 실행하면 다음 오류가 발생합니다.

    error[E0616]: field `username` of struct `User` is private
      --> src/main.rs:28:42
       |
    28 |     println!("The username is: {}", user.username);
       |                                          ^^^^^^^^ private field

    error[E0616]: field `password_hash` of struct `User` is private
      --> src/main.rs:29:42
       |
    29 |     println!("The password is: {}", user.password_hash);
       |                                          ^^^^^^^^^^^^^ private field

    error: aborting due to 2 previous errors

이 오류 정보는 특정 모듈의 각 부분에 프로그램의 어떤 부분이 액세스할 수 있는지를 제어하고자 할 때 유용합니다. username 필드에 대한 읽기 권한을 부여하고 password 필드에 대한 쓰기 권한을 부여하면서 프라이빗으로 유지하려면 getter 및 setter 메서드를 사용할 수 있습니다.

mod authentication {

    // ...

    impl User {

    // ...

        pub fn get_username(&self) -> &String {
            &self.username
        }
    
        pub fn set_password(&mut self, new_password: &str) {
            self.password_hash = hash_password(new_password)
        }
    }
}

이제 모든 읽기 및 쓰기 시도는 authentication 모듈에 의해 제어됩니다.

이 단원에 대한 코드를 보려면 이 Rust Playground 링크를 참조하세요.