프렐류드

프렐류드 (Preludes)

Rust 코드를 쓰다 보면 Vec이나 Box 같은 이름을 use 없이 바로 쓰게 돼요. 이게 가능한 이유가 바로 프렐류드(prelude)예요. 어떤 이름들이 자동으로 스코프에 들어오는지, 그 규칙을 이 페이지에서 정리해볼게요.

출처: Rust Reference

본문

**프렐류드(prelude)**는 크레이트의 모든 모듈로 자동으로 스코프에 들어오는 이름들의 모음이에요. 이 프렐류드 이름들은 모듈 자체의 일부가 아니에요. 이름 분석 중에 암묵적으로 조회되죠. 예를 들어 Box 같은 것이 모든 모듈에서 스코프에 있더라도, 현재 모듈의 멤버가 아니기 때문에 self::Box로는 참조할 수 없어요.

프렐류드에는 여러 종류가 있어요.

  • 표준 라이브러리 프렐류드 (Standard library prelude)
  • 외부 프렐류드 (Extern prelude)
  • 언어 프렐류드 (Language prelude)
  • macro_use 프렐류드
  • 도구 프렐류드 (Tool prelude)

표준 라이브러리 프렐류드

각 크레이트는 표준 라이브러리 프렐류드를 가지는데, 이는 단일 표준 라이브러리 모듈의 이름들로 구성돼요. 사용되는 모듈은 크레이트의 에디션(edition)과, 크레이트에 no_std 속성이 적용되었는지 여부에 따라 달라져요.

에디션 no_std 미적용 no_std 적용
2015 std::prelude::rust_2015 core::prelude::rust_2015
2018 std::prelude::rust_2018 core::prelude::rust_2018
2021 std::prelude::rust_2021 core::prelude::rust_2021
2024 std::prelude::rust_2024 core::prelude::rust_2024

참고: std::prelude::rust_2015std::prelude::rust_2018std::prelude::v1과 내용이 같아요. core::prelude::rust_2015core::prelude::rust_2018core::prelude::v1과 내용이 같아요.

참고: 표준 라이브러리 프렐류드 때문에 core::panic! 또는 std::panic! 중 하나가 스코프에 들어오고, 사용자가 작성한 글롭 임포트가 다른 하나를 스코프에 들여올 때, panic!은 모호함에도 불구하고 현재 rustc는 그 사용을 허용해요. 사용자가 작성한 글롭 임포트가 우선하여 이 모호성을 해결해요.

외부 프렐류드 (Extern prelude)

루트 모듈에서 extern crate로 임포트하거나 (rustc--extern 플래그처럼) 컴파일러에 제공된 외부 크레이트들은 외부 프렐류드에 추가돼요. extern crate orig_name as new_name처럼 별칭으로 임포트하면, 대신 new_name 심볼이 프렐류드에 추가돼요.

core 크레이트는 항상 외부 프렐류드에 추가돼요. std 크레이트는 크레이트 루트에 no_std 속성이 지정되지 않는 한 추가돼요.

2018 에디션 차이

2015 에디션에서는 외부 프렐류드의 크레이트를 use 선언으로 참조할 수 없어서, 보통 extern crate 선언을 포함해 이들을 스코프로 가져오는 것이 일반적인 관례였어요. 2018 에디션부터는 use 선언이 외부 프렐류드의 크레이트를 참조할 수 있으므로, extern crate를 쓰는 것은 비관용적(unidiomatic)으로 간주돼요.

참고: alloc, test처럼 rustc와 함께 배포되는 추가 크레이트들은 Cargo를 사용할 때 --extern 플래그에 자동으로 포함되지 않아요. 2018 에디션에서도 extern crate 선언으로 스코프에 가져와야 해요.

extern crate alloc;
use alloc::rc::Rc;

Cargo는 proc-macro 크레이트에 대해서만 proc_macro를 외부 프렐류드로 가져와요.

no_std 속성

no_std 속성은 std 크레이트가 자동으로 링크되지 않게 하고, 대신 표준 라이브러리 프렐류드가 core 프렐류드를 사용하도록 해요.

#![no_std]

참고: no_std를 쓰는 것은 크레이트가 표준 라이브러리를 지원하지 않는 플랫폼을 대상으로 하거나, 의도적으로 표준 라이브러리의 기능을 사용하지 않을 때 유용해요. 그 기능은 주로 동적 메모리 할당 (예: Box, Vec)과 파일·네트워크 기능 (예: std::fs, std::io)이에요.

경고: no_std를 쓴다고 표준 라이브러리가 링크되지 않는 것은 아니에요. 크레이트나 그 의존성 중 하나에서 extern crate std를 쓰는 것은 여전히 유효하며, 이는 컴파일러가 std 크레이트를 프로그램에 링크하게 만들어요.

no_std 속성은 MetaWord 문법을 사용해요. 크레이트 루트에만 적용할 수 있고, 한 형태에 몇 번이든 사용할 수 있어요. (rustc는 첫 사용 이후의 사용에 대해 린트를 걸어요.) no_std 속성은 표준 라이브러리 프렐류드가 std 프렐류드 대신 core 프렐류드를 사용하도록 바꿔요.

2018 에디션 차이

2018 에디션 이전에는 std가 기본적으로 크레이트 루트에 주입됐어요. no_std가 지정되면 대신 core가 주입됐죠. 2018 에디션부터는 no_std 지정 여부와 무관하게 둘 다 크레이트 루트에 주입되지 않아요.

언어 프렐류드 (Language prelude)

언어 프렐류드는 언어에 내장된 타입과 속성의 이름을 포함해요. 언어 프렐류드는 항상 스코프에 있어요. 여기에는 다음이 포함돼요.

타입 네임스페이스

  • 부울 타입 — bool
  • char
  • str
  • 정수 타입 — i8, i16, i32, i64, i128, u8, u16, u32, u64, u128
  • 기계 의존 정수 타입 — usize, isize
  • 부동소수점 타입 — f32, f64

매크로 네임스페이스

  • 내장 속성 (Built-in attributes)
  • 내장 derive 매크로

macro_use 프렐류드

macro_use 프렐류드는 extern crate에 적용된 macro_use 속성으로 임포트된 외부 크레이트의 매크로들을 포함해요.

도구 프렐류드 (Tool prelude)

도구 프렐류드는 타입 네임스페이스에서 외부 도구들의 도구 이름을 포함해요. 자세한 내용은 도구 속성 섹션에서 볼 수 있어요.

no_implicit_prelude 속성

no_implicit_prelude 속성은 암묵적 프렐류드들이 스코프로 들어오지 않게 막는 데 사용돼요.

// 이 속성을 크레이트 루트에 적용하면 모든 모듈에 영향.
#![no_implicit_prelude]

// 또는 모듈에 적용하면 그 모듈과 하위 모듈에만 영향.
#[no_implicit_prelude]
mod example {
    // ...
}

no_implicit_prelude 속성은 MetaWord 문법을 사용해요. 크레이트나 모듈에만 적용할 수 있어요. (다른 위치에서의 use는 rustc가 무시하지만 린트를 걸어요. 이는 미래에 오류가 될 수 있어요.) 한 형태에 몇 번이든 사용할 수 있어요. (rustc는 첫 사용 이후의 사용에 대해 린트를 걸어요.)

no_implicit_prelude 속성은 해당 모듈과 하위 모듈에 대해 표준 라이브러리 프렐류드, 외부 프렐류드, macro_use 프렐류드, 도구 프렐류드가 스코프로 들어오지 않게 막아요.

참고: #![no_implicit_prelude]에도 불구하고, rustc는 현재 특정 매크로들을 암묵적으로 스코프로 가져와요. 그 매크로들은 다음과 같아요: assert!, cfg!, cfg_select!, column!, compile_error!, concat!, concat_bytes!, env!, file!, format_args!, include!, include_bytes!, include_str!, line!, module_path!, option_env!, panic!, stringify!, unreachable!.

예를 들어 이건 동작해요:

#![no_implicit_prelude]
fn main() { assert!(true); }

이 동작에 의존하지 마세요. 미래에 제거될 수 있어요. #![no_implicit_prelude]를 쓸 때는 항상 필요한 아이템들을 명시적으로 스코프에 가져오세요.

no_implicit_prelude 속성은 언어 프렐류드에는 영향을 주지 않아요.

2018 에디션 차이

2015 에디션에서 no_implicit_prelude 속성은 macro_use 프렐류드에 영향을 주지 않고, 표준 라이브러리에서 내보낸 모든 매크로가 여전히 macro_use 프렐류드에 포함됐어요. 2018 에디션부터는 이 속성이 macro_use 프렐류드를 제거해요.

더 알아보기 (Learn more)

  • Rust Reference의 프렐류드 문서에서 전체 내용을 확인할 수 있어요.
  • Rust Reference의 이름 분석 문서에서 프렐류드가 어떻게 조회되는지 더 자세히 다룬답니다.
  • Rust Reference의 no_std 관련 크레이트 문서를 통해 표준 라이브러리 없이 개발하는 방법을 살펴볼 수 있어요.