본문으로 건너뛰기

안동민 개발노트

본문 시작

`use` 키워드로 경로를 스코프 안으로 가져오기

use·as·pub use와 중첩·글롭 경로를 사용해 모듈 및 외부 패키지의 이름을 현재 스코프에 명확하게 가져옵니다.

함수 호출을 위해서 경로를 작성하는 것은 불편하고 반복적인 느낌을 줄 수 있습니다.

예제 6-7에서는 절대 경로를 사용하건 상대 경로를 사용하건, add_to_waitlist 호출할 때마다 front_of_house, hosting 모듈을 매번 지정해줘야 했죠.

다행히도 이 과정을 단축할 방법이 있습니다.

use 선언은 경로가 가리키는 대상을 옮기거나 복사하지 않고 현재 스코프에 로컬 이름 바인딩을 만듭니다. 그러면 그 스코프 안에서 짧은 이름을 사용할 수 있습니다.

예제 6-11은 crate::front_of_house::hosting 모듈을 eat_at_restaurant 함수가 존재하는 스코프로 가져와, eat_at_restaurant 함수 내에서 add_to_waitlist 함수를 hosting::add_to_waitlist 경로만으로 호출하는 예제입니다.

예제 6-11: use 키워드로 모듈을 스코프 안으로 가져오기
src/lib.rs
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}

스코프에 use 키워드와 경로를 작성하는 건 파일 시스템에서 심볼릭 링크(symbolic link)를 생성하는 것과 유사합니다.

크레이트 루트에 use crate::front_of_house::hosting를 작성하면 해당 스코프에서 hosting 모듈을 크레이트 루트에 정의한 것처럼 사용할 수 있습니다.

use의 원본 경로도 다른 경로와 똑같이 가시성 검사를 받습니다. 따라서 use는 비공개 경계를 우회하거나 대상의 가시성을 넓히지 않습니다.

use가 사용된 특정한 스코프에서만 단축경로가 만들어진다는 점을 주의하세요.

예제 6-12에서는 eat_at_restaurant 함수를 새로운 자식 모듈 customer로 옮겼는데, 이러면 use 구문과 다른 스코프가 되므로, 이 함수는 컴파일 되지 않습니다.

예제 6-12: use 구문은 사용된 스코프 내에서만 적용됩니다
src/lib.rs
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting;

mod customer {
    pub fn eat_at_restaurant() {
        hosting::add_to_waitlist();
    }
}

컴파일러는 customer 모듈 내에 더 이상 단축경로가 적용되지 않음을 알려줍니다.

$ cargo build
   Compiling restaurant v0.1.0 (file:///projects/restaurant)
warning: unused import: `crate::front_of_house::hosting`
 --> src/lib.rs:7:5
  |
7 | use crate::front_of_house::hosting;
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error[E0433]: failed to resolve: use of unresolved module or unlinked crate `hosting`
  --> src/lib.rs:11:9
   |
11 |         hosting::add_to_waitlist();
   |         ^^^^^^^ use of unresolved module or unlinked crate `hosting`

For more information about this error, try `rustc --explain E0433`.
warning: `restaurant` (lib) generated 1 warning
error: could not compile `restaurant` due to previous error; 1 warning emitted

use가 해당 스코프 안에서 더 이상 사용되지 않는다는 경고도 있음을 주목하세요!

이 문제를 해결하려면 usecustomer 모듈 안쪽으로 옮기거나, customer 모듈 내에서 super::hosting를 써서 부모 모듈로의 단축경로를 참조하면 됩니다.


보편적인 use 경로 작성법

use가 현재 스코프에 이름을 바인딩하는 규칙과 함수·타입 관용, 별칭, 외부 크레이트, 중첩 self, 글롭 제한을 정리한 표

LOCAL BINDING · READABLE ORIGIN

use는 현재 스코프에 이름을 바인딩한다

대상을 복사하거나 이동하지 않고, 접근 가능한 경로에 짧은 로컬 이름을 붙입니다. 이름을 어디에 둘지는 언어 규칙이고, 어떤 이름까지 직접 가져올지는 읽기 관용입니다.

언어 규칙 · 스코프와 가시성

바인딩은 선언이 놓인 스코프에 생기며 자식 모듈로 자동 복제되지 않습니다. 원본 경로가 호출 위치에서 접근 가능해야 하고, use는 private 경계를 우회하지 않습니다.

스타일 관용 · 호출부의 출처

함수는 부모 모듈을 가져와 출처를 남기고, 구조체·열거형 같은 타입과 트레이트는 아이템을 직접 가져오는 방식이 관용적입니다. 이름 충돌 시에는 부모 모듈이나 별칭을 씁니다.

use 형태별로 만들어지는 바인딩과 선택 기준
상황 만들어지는 이름 규칙과 선택 기준
현재 스코프 use 선언이 있는 스코프에 로컬 바인딩을 만듭니다. 자식 모듈은 자동으로 이어받지 않습니다. 필요하면 자식에서 다시 가져오거나 super::hosting처럼 부모의 바인딩을 명시합니다.
가시성 접근 가능한 원본 경로와 같은 대상을 가리키는 이름입니다. 원본 경로의 privacy 검사를 그대로 받으며, 바인딩만으로 대상의 공개 범위를 넓히지 않습니다.
함수 관용 부모 모듈 이름을 가져와 모듈을 통해 호출합니다. 전체 경로 반복은 줄이면서 함수가 로컬 정의가 아님을 호출부에 남기는 스타일 관용입니다.
타입·트레이트 관용 HashMap, Rng처럼 아이템 이름을 직접 가져옵니다. 타입 표기를 간결하게 하고, 트레이트 메서드를 사용할 때 필요한 트레이트를 스코프에 둡니다. 언어가 강제하는 가져오기 모양은 아닙니다.
이름 충돌 부모 모듈을 남기거나 as로 새 로컬 이름을 만듭니다. 두 방법 모두 유효합니다. 별칭은 IoResult처럼 출처나 역할이 읽히게 정합니다.
외부 크레이트 Cargo가 호출자에게 바인딩한 크레이트 이름에서 경로가 시작됩니다. 의존성 선언이 크레이트를 연결하고 use는 그 안의 이름을 현재 스코프에 묶습니다. 의존성 이름을 바꾸면 첫 세그먼트도 바뀝니다.
중첩 self 공통 부모와 자식 아이템을 한 선언에서 함께 바인딩합니다. self는 중괄호 앞의 부모 경로 자체를 뜻합니다. 중첩은 중복만 접고 각 원본 경로의 의미는 유지합니다.
글롭 *가 경로 아래의 접근 가능한 이름들을 한꺼번에 가져옵니다. 출처가 흐려지고 의존성 업데이트가 새 충돌을 만들 수 있습니다. 테스트나 의도적으로 설계한 프렐루드처럼 경계가 분명한 곳에 제한합니다.
현재 스코프
선언이 놓인 스코프에만 로컬 이름이 생깁니다.
자식에서는 다시 가져오거나 부모 바인딩을 명시합니다.
가시성
원본 경로의 privacy 검사를 그대로 받습니다.
use는 private 경계나 공개 범위를 바꾸지 않습니다.
함수 관용
부모 모듈을 가져와 모듈 이름을 통해 호출합니다.
함수의 출처를 호출부에 남기는 관용이지 언어 규칙은 아닙니다.
타입·트레이트 관용
아이템 이름을 직접 가져오는 방식이 관용적입니다.
타입 표기와 트레이트 메서드 사용을 간결하게 합니다.
이름 충돌
부모 모듈을 남기거나 as 별칭을 사용합니다.
별칭은 출처나 역할이 드러나는 이름으로 정합니다.
외부 크레이트
Cargo가 호출자에게 바인딩한 크레이트 이름에서 시작합니다.
의존성 연결과 로컬 이름 바인딩은 서로 다른 단계입니다.
중첩 self
공통 부모 경로 자체와 자식 아이템을 함께 가져옵니다.
경로 의미는 유지하고 반복되는 접두사만 접습니다.
글롭
*는 접근 가능한 이름을 한꺼번에 가져옵니다.
출처와 향후 충돌을 숨기므로 목적이 분명한 범위에 제한합니다.

검토 순서: 선언 위치 → 원본 경로의 접근 가능성 → 호출부에서 보일 출처 → 충돌과 유지보수 위험. 문법상 가능함과 관용적으로 읽기 좋음을 구분합니다.

예제 6-11에서 add_to_waitlist 함수까지 경로를 전부 작성하지 않고, use crate::front_of_house::hosting 까지만 작성한 뒤 hosting::add_to_waitlist 코드로 함수를 호출하는 점이 의아하실 수도 있습니다.

예제 6-13처럼 작성하면 안 되는 걸까요?

예제 6-13: use 키워드로 add_to_waitlist 함수를 직접 가져오기(보편적이지 않은 작성 방식)
src/lib.rs
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

use crate::front_of_house::hosting::add_to_waitlist;

pub fn eat_at_restaurant() {
    add_to_waitlist();
}

예제 6-11과 6-13의 동작은 동일하지만, 예제 6-11 코드가 use 키워드로 스코프에 함수를 가져올 때의 관용적인 코드입니다. 이는 언어가 강제하는 규칙이 아니라 출처를 읽기 쉽게 남기는 스타일 관용입니다.

함수의 부모 모듈을 use 키워드로 가져오면 함수를 호출할 때 부모 모듈을 특정해야 합니다.

함수 호출 시 부모 모듈을 특정하면 전체 경로를 반복하는 것을 최소화하면서도 함수가 로컬에 정의되어 있지 않음을 명백히 보여주게 됩니다.

예제 6-13의 코드는 add_to_waitlist가 어디에 정의되어 있는지 불분명합니다.

한편, use 키워드로 구조체나 열거형 등의 타 아이템을 가져올 시에는 전체 경로를 작성하는 것이 보편적입니다.

예제 6-14는 HashMap 표준 라이브러리 구조체를 바이너리 크레이트의 스코프로 가져오는 관용적인 코드 예시입니다.

예제 6-14: 보편적인 방식으로 HashMap을 스코프로 가져오기
src/main.rs
use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();
    map.insert(1, 2);
}

이러한 관용이 탄생하게 된 명확한 이유는 없습니다.

어쩌다 보니 관습이 생겼고, 사람들이 이 방식대로 러스트 코드를 읽고 쓰는 데에 익숙해졌을 뿐입니다.

하지만, 동일한 이름의 아이템을 여럿 가져오는 경우는 이 방식을 사용하지 않습니다.

러스트가 허용하지 않기 때문이죠.

예제 6-15는 각각 다른 모듈 내에 위치하지만 이름이 같은 두 개의 Result 타입을 스코프로 가져와 사용하는 예시입니다.

예제 6-15: 이름이 같은 두 개의 타입을 동일한 스코프에 가져오려면 부모 모듈을 반드시 명시해야 합니다.
src/lib.rs
use std::fmt;
use std::io;

fn function1() -> fmt::Result {
    // --생략--
    Ok(())
}

fn function2() -> io::Result<()> {
    // --생략--
    Ok(())
}

보시다시피 부모 모듈을 명시하여 두 개의 Result 타입을 구별하고 있습니다.

만약 use std::fmt::Result, use std::io::Result로 작성한다면, 동일한 스코프 내에 두 개의 Result 타입이 존재하므로 러스트는 우리가 어떤 Result 타입을 사용했는지 알 수 없습니다.


as 키워드로 새로운 이름 제공하기

use 키워드로 동일한 이름의 타입을 스코프로 여러 개 가져올 경우의 또 다른 해결 방법이 있습니다.

경로 뒤에 as 키워드를 작성하고 새로운 로컬 이름, 즉 별칭을 지정하면 됩니다.

예제 6-16은 as 키워드를 이용해 예제 6-15 코드의 Result 타입 이름 중 하나를 변경한 예제입니다.

예제 6-16: 스코프 안으로 가져온 타입의 이름을 as 키워드로 변경하기
src/lib.rs
use std::fmt::Result;
use std::io::Result as IoResult;

fn function1() -> Result {
    // --생략--
    Ok(())
}

fn function2() -> IoResult<()> {
    // --생략--
    Ok(())
}

두 번째 use 구문에서는, 앞서 스코프 안으로 가져온 std::fmtResult와 충돌을 방지하기 위해 std::io::Result 타입의 이름을 IoResult로 새롭게 지정합니다.

예제 6-15, 예제 6-16은 둘 다 관용적인 방식이므로, 원하는 방식을 선택하시면 됩니다!


pub use로 다시 내보내기

use 키워드로 이름을 가져올 경우, 해당 이름은 새 위치의 스코프에서 비공개가 됩니다.

pubuse를 결합하면 우리 코드를 호출하는 코드가 해당 스코프에 정의된 것처럼 해당 이름을 참조할 수 있습니다.

이 기법은 아이템을 스코프로 가져오는 동시에 다른 곳에서 아이템을 가져갈 수 있도록 만들기 때문에, 다시 내보내기(re-exporting) 라고 합니다.

다만 pub use는 원본 아이템의 가시성을 임의로 넓히지 못합니다. 재내보내기 선언이 원본 경로에 접근할 수 있어야 하고, 외부에 pub으로 재내보낼 이름은 그 범위만큼 공개 가능한 아이템이어야 합니다. 비공개 조상 모듈 뒤에 선언된 공개 아이템은 새 공개 경로로 재내보낼 수 있지만, 비공개 아이템 자체를 pub use만으로 외부에 공개할 수는 없습니다.

예제 6-17은 예제 6-11 코드의 usepub use로 변경한 예제입니다.

예제 6-17: 다른 스코프의 코드에서 사용할 수 있도록 pub use 사용
src/lib.rs
mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

pub use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}

위와 같이 변경하기 전이라면 외부 코드가 add_to_waitlist 함수를 원래 경로로 호출하려면 front_of_house 모듈도 pub이어야 합니다. 예제처럼 front_of_house가 비공개인 상태에서는 그 원래 경로를 외부에서 사용할 수 없습니다.

위의 pub use가 루트 모듈로부터 hosting 모듈을 다시 내보냈으므로, 이제 외부 코드는 restaurant::hosting::add_to_waitlist() 경로를 대신 사용할 수 있습니다.

다시 내보내기 기법은 작성한 코드의 구조 내부와, 그 코드를 사용할 프로그래머들이 예상할법한 해당 분야의 구조가 서로 다를 때 유용합니다.

레스토랑 비유 예제를 예로 들어보죠.

레스토랑을 운영하는 직원들의 머릿속에서는 ‘접객 부서’와 ‘지원 부서’가 나뉘어 있습니다.

하지만 레스토랑을 방문하는 고객들은 레스토랑의 부서를 그런 용어로 나누어 생각하지 않겠죠.

pub use를 사용하면 코드를 작성할 때의 구조와, 노출할 때의 구조를 다르게 만들 수 있습니다.

라이브러리를 제작하는 프로그래머와, 라이브러리를 사용하는 프로그래머 모두를 위한 라이브러리를 구성하는 데 큰 도움이 되죠.

pub use에 대한 또 다른 예제, 그리고 이것이 여러분의 크레이트 문서에 어떤 영향을 주는지에 대해서는 13장의 pub use를 사용하여 편리한 공개 API 내보내기’절에서 살펴보겠습니다.

pub use가 내부 모듈 구조와 외부 공개 API 경로를 분리하는 방식과 원본 가시성, 별칭, 중첩, 글롭 재내보내기 제한을 정리한 표

RE-EXPORT · API BOUNDARY

pub use는 공개 경로를 설계하지만 가시성을 발명하지 않는다

공개 가능한 이름을 새 스코프에서 다시 내보내 사용자가 의존할 경로를 만듭니다. private 내부 모듈은 숨길 수 있지만 private 아이템 자체를 외부 공개로 승격할 수는 없습니다.

내부 모듈 트리

구현자는 접객 영역 아래에 공개 hosting 모듈을 두되 그 조상 모듈은 private으로 유지할 수 있습니다. 루트의 재내보내기 선언은 내부에서 접근 가능한 원본 경로를 해석합니다.

외부 공개 API

사용자는 크레이트 루트에서 재내보낸 hosting 경로를 사용합니다. 원래 조상 모듈은 공개되지 않으며, 내부 이동 시 재내보내기 한 곳을 고쳐 공개 경로를 유지할 수 있습니다.

재내보내기가 만드는 공개 경로와 넘을 수 없는 가시성 경계
검토 항목 가능한 설계 남는 제약
use 현재 스코프에서 사용할 private 로컬 바인딩을 만듭니다. 그 이름은 외부 API가 아니며 자식 스코프에 자동으로 복제되지 않습니다.
pub use 가져온 이름을 재내보내 새 공개 API 경로를 만듭니다. 재내보내기 선언이 원본 경로에 접근할 수 있어야 하며 대상도 공개 범위를 충족해야 합니다.
private 조상 private 모듈 안의 공개 아이템을 접근 가능한 위치에서 새 공개 경로로 재내보낼 수 있습니다. 재내보내기는 원래 조상을 공개하지 않습니다. 외부 사용자는 private 조상을 지나는 원래 경로를 쓸 수 없습니다.
private 아이템 같거나 더 좁은 제한 범위 안에서만 해당 가시성에 맞는 이름을 다시 바인딩할 수 있습니다. private 또는 크레이트 한정 아이템을 단순히 pub use하여 외부 공개로 넓힐 수 없습니다.
API 이름 as 별칭으로 사용자의 분야 언어에 맞는 공개 이름을 제공할 수 있습니다. 별칭도 동일한 원본 가시성 검사를 받으며, 공개 이름 변경은 사용자에게 API 변경이 됩니다.
중첩 재내보내기 중괄호와 self로 공통 경로의 여러 공개 이름을 묶을 수 있습니다. 중첩 문법은 선언만 압축합니다. 각 대상의 접근 가능성과 공개 가능 범위는 따로 검사됩니다.
글롭 재내보내기 *로 접근 가능한 여러 이름을 공개 표면에 포함할 수 있습니다. 의존성이나 내부 모듈의 새 공개 이름이 API에 뜻밖에 추가될 수 있어 의도적인 프렐루드 외에는 명시 목록이 안전합니다.
외부 크레이트 의존 크레이트의 공개 이름도 별칭이나 새 모듈 경로 아래에서 재내보낼 수 있습니다. 사용자는 그 타입과 경로에 의존하므로 의존성 교체·버전 변경까지 공개 API 호환성 판단에 포함해야 합니다.
use
현재 스코프를 위한 private 로컬 바인딩입니다.
반복 경로와 호출부 출처를 정리하는 내부 도구입니다.
pub use
가져온 이름을 새 공개 경로에서 다시 내보냅니다.
원본 경로 접근과 대상 가시성 조건을 모두 만족해야 합니다.
private 조상
그 안의 공개 아이템을 새 공개 경로로 재내보낼 수 있습니다.
원래 조상은 계속 private이며 외부 원래 경로는 막혀 있습니다.
private 아이템
재내보내기만으로 외부 공개 범위까지 넓힐 수 없습니다.
재내보내기 가시성은 원본이 허용하는 범위를 넘지 못합니다.
API 이름
as 별칭으로 사용자가 볼 공개 이름을 설계할 수 있습니다.
공개 이름 변경은 사용자에게 API 변경입니다.
중첩 재내보내기
중괄호와 self로 공통 접두사를 접습니다.
각 대상의 가시성 검사는 그대로 따로 수행됩니다.
글롭 재내보내기
*는 공개 API가 의도하지 않게 늘어날 위험이 있습니다.
프렐루드 외에는 명시적인 공개 이름 목록이 안전합니다.
외부 크레이트
의존 크레이트의 공개 이름도 새 경로로 재내보낼 수 있습니다.
의존성 변화까지 공개 API 호환성에 포함해 판단합니다.

공개 API 검토 순서: 재내보내기 위치에서 원본 경로 접근 → 대상의 최대 가시성 → 사용자가 볼 이름과 경로 → 내부 이동·의존성 변경 시 호환성.


외부 패키지 사용하기

2장에서는 난수 생성을 위해 rand라는 외부 패키지를 사용하는 추리 게임 프로젝트를 만들었습니다.

rand 패키지를 프로젝트에서 사용하기 위해서 Cargo.toml에 다음 줄을 추가했었죠.

Cargo.toml
rand = "0.8.5"

Cargo.tomlrand를 의존성으로 추가하면 Cargo가 crates.io에서 rand 패키지를 비롯한 모든 의존성을 다운로드하고 호출자에게 바인딩된 크레이트 이름을 경로에서 사용할 수 있게 합니다. 의존성 이름을 바꾸었다면 코드에서는 그 로컬 이름을 사용합니다.

그 후, 구현하고 있는 패키지의 스코프로 rand 정의를 가져오기 위해 use 키워드와 크레이트 이름인 rand를 쓰고 가져올 아이템을 나열했습니다.

1장 ‘임의의 숫자 생성하기’ 절을 다시 떠올려 보죠.

Rng 트레이트를 스코프로 가져오고 rand::thread_rng 함수를 호출했었습니다.

use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1..=100);
}

러스트 커뮤니티 구성원들이 crates.io에서 이용 가능한 다양한 패키지를 만들어왔고, 이들 모두 같은 단계를 거쳐서 여러분 패키지에 가져올 수 있습니다.

패키지를 Cargo.toml에 의존성으로 추가한 뒤 크레이트 이름으로 시작하는 경로를 직접 쓰거나, 반복해서 사용할 아이템을 use로 현재 스코프에 바인딩하면 됩니다. use가 외부 패키지를 링크하는 것은 아닙니다.

알아 두어야 할 것이 있다면 std 표준 라이브러리도 마찬가지로 외부 크레이트라는 겁니다.

러스트 도구체인과 함께 제공되기 때문에 Cargo.toml에 추가할 필요는 없습니다. 표준 라이브러리 아이템도 전체 경로로 직접 참조하거나 use로 짧은 이름을 바인딩할 수 있습니다.

예를 들어, HashMap을 가져오는 코드는 다음과 같습니다.

use std::collections::HashMap;

위는 표준 라이브러리 크레이트의 이름인 std 로 시작하는 절대 경로입니다.


중첩 경로를 사용하여 대량의 use 나열을 정리하기

동일한 크레이트나 동일한 모듈 내에 정의된 아이템을 여럿 사용할 경우, 각 아이템 당 한 줄씩 코드를 나열하면 수직 방향으로 너무 많은 영역을 차지합니다.

예시를 살펴봅시다.

추리 게임의 예제 1-4에서 작성했던 다음 두 use 문은 std 내 아이템을 스코프로 가져옵니다.

src/main.rs
// --생략--
use std::cmp::Ordering;
use std::io;
// --생략--

그대신 중첩 경로를 사용하여 동일한 아이템을 한 줄로 가져올 수 있습니다.

경로의 공통된 부분을 작성하고 콜론 두 개를 붙인 다음, 중괄호 내에 경로가 다른 부분을 나열합니다.

예시는 예제 6-18과 같습니다.

예제 6-18: 중첩 경로를 사용해, 경로의 앞부분이 같은 여러 아이템을 스코프로 가져오기
src/main.rs
// --생략--
use std::{cmp::Ordering, io};
// --생략--

규모가 큰 프로그램이라면, 동일한 크레이트나 모듈에서 여러 아이템을 가져올 때 중첩 경로를 사용함으로써 많은 use 구문을 줄일 수 있습니다!

중첩 경로는 경로의 아무 단계에서 사용할 수 있으며, 하위 경로가 동일한 use 구문이 많을 때 특히 빛을 발합니다.

다음 예제 6-19는 두 use 구문의 예시입니다.

하나는 std::io를 스코프로 가져오고, 다른 하나는 std::io::Write를 스코프로 가져옵니다.

예제 6-19: 하위 경로가 같은 두 use 구문
src/lib.rs
use std::io;
use std::io::Write;

두 경로에서 중복되는 부분은 std::io입니다.

또한 std::io는 첫 번째 경로 그 자체이기도 합니다.

중첩 경로에 self를 작성하면 두 경로를 하나의 use 구문으로 합칠 수 있습니다.

예제 6-20: 예제 6-19의 두 경로를 use 구문 하나로 합치기
src/lib.rs
use std::io::{self, Write};

이 한 줄로 std::io, std::io::Write 둘 다 스코프로 가져올 수 있습니다.


글롭 연산자

경로에 글롭(glob) 연산자 *를 붙이면 경로 안에 정의된 모든 공개 아이템을 가져올 수 있습니다.

use std::collections::*;

use 구문은 std::collections 내에 정의된 모든 공개 아이템을 현재 스코프로 가져옵니다.

하지만 글롭 연산자는 코드에 사용된 어떤 이름이 어느 곳에 정의되어 있는지 파악하기 어렵게 만들 수 있으므로, 사용에 주의해야 합니다.

의존성의 새 버전이 공개 이름을 추가하면 글롭으로 들어오는 이름도 함께 바뀌어 기존 이름과 충돌할 수 있습니다. 따라서 일반 코드에서는 가져올 이름을 명시하고, 테스트 모듈이나 의도적으로 설계한 프렐루드처럼 범위와 목적이 분명한 곳에 글롭을 제한하는 편이 안전합니다.

글롭 연산자는 테스트할 모든 아이템을 tests 모듈로 가져오는 용도로 자주 사용됩니다. (10장 ‘테스트 작성 방법’에서 다룰 예정입니다.)

또한 프렐루드 패턴의 일부로 사용되기도 하며, 자세한 내용은 표준 라이브러리 문서를 참고 바랍니다.

use 구문을 정리할 때는 짧은 이름 자체보다 바인딩이 적용되는 스코프, 호출부에서 보이는 출처, 충돌 시 별칭의 의미, 외부에 약속할 공개 경로를 기준으로 삼는 것이 좋습니다.