문서는 개발자와 사용자 간의 다리 역할을 합니다. Rust 생태계에서 문서는 Rustdoc이라는 정교한 문서 생성 도구를 통해 1급 시민으로 격상됩니다. Rustdoc은 표준 Rust 배포판에 포함되어 있습니다. 다른 많은 언어의 문서 도구와 달리 Rustdoc은 단순히 정적 문서를 생성하지 않습니다. 그것은 코드 발견 가능성과 사용성을 향상시키는 대화형, 테스트 가능하며 풍부한 형식의 문서 웹사이트를 생성합니다.
Rust 개발자를 위해 Apidog는 HTTP API에 대한 대화형 테스트 기능, 시각적 응답 형식화 및 협업 기능을 갖춘 포괄적인 API 문서화 기능을 제공합니다.

Apidog은 엔드포인트, 요청/응답 형식 및 HTTP 사양을 문서화하는 데 중점을 두고 있으며, Rustdoc은 Rust 크레이트를 구성하는 구조체, 함수, 특성 및 기타 프로그래밍 구성 요소를 언어 수준에서 문서화하는 데 전문화되어 있습니다. 두 시스템은 복잡한 기술 시스템을 철저하고 정확하며 사용 가능한 문서를 통해 더욱 접근 가능하게 만드는 기본 목표를 공유합니다.

Rustdoc란 무엇인가요?
Rustdoc은 Rust 소스 코드를 구문 분석하고 특별한 문서 주석을 사용하여 브라우징 가능한 문서 웹사이트를 형성하는 HTML, CSS 및 JavaScript 파일을 생성하는 명령줄 도구입니다. Rustdoc의 핵심은 코드에서 문서 주석을 추출하고 이를 구조화된 문서로 변환하는 것입니다.
Rustdoc의 기본 작업은 다음을 포함합니다:
- Rust 소스 파일을 구문 분석하여 문서 주석을 추출합니다.
- 그 주석을 Markdown에서 HTML로 변환합니다.
- 검색 가능하고 탐색 가능한 웹사이트 구조를 생성합니다.
- 문서에서 코드 예제를 추출하고 테스트를 위해 준비합니다.
- 항목 간의 교차 참조를 생성합니다.
- 최종 문서를 위한 정적 자산을 생성합니다.
직접 호출할 때, Rustdoc 바이너리는 Rust 소스 파일을 입력으로 받아들입니다:
$ rustdoc src/lib.rs --crate-name my_crate
이 명령은 lib.rs
파일을 처리하고 기본적으로 문서를 doc
디렉터리에 출력합니다. 문서는 계층적으로 구조화되어 있으며, 모듈, 구조체, 열거형, 특성 및 기타 Rust 구성 요소에 대한 별도의 페이지로 구성됩니다.
내부적으로 Rustdoc은 Rust 컴파일러의 내부 API를 활용하여 코드의 구문 분석 및 이해를 수행합니다. 이러한 컴파일러와의 긴밀한 통합은 Rustdoc이 정확한 교차 참조를 생성하고, 적절하게 유형 서명을 문서화하며, 코드 예제가 실제로 컴파일되고 올바르게 실행되는지 확인할 수 있도록 합니다.
Rust의 문서 주석
Rust의 문서는 일반 코드 주석과 다른 특별한 주석 구문에 의존합니다. 두 가지 주요 유형의 문서 주석이 있습니다:
외부 문서 주석 (///
)
외부 문서 주석은 자신 다음에 오는 항목을 문서화하며, 세 개의 슬래시로 표시됩니다:
/// 아래 함수에 대한 문서 주석입니다.
/// 여러 줄에 걸쳐 작성할 수 있으며, Markdown 형식을 지원합니다.
pub fn documented_function() -> bool {
true
}
이 주석은 코드베이스의 함수, 구조체, 열거형, 특성, 모듈 및 기타 항목을 설명합니다. 이들은 자신이 문서화하는 항목 외부에 존재하기 때문에 "외부" 문서라고 불립니다.
내부 문서 주석 (//!
)
내부 문서 주석은 자신이 있는 항목을 문서화하며, //!
로 표시됩니다:
//! 이 모듈은 구성 파일을 구문 분석하기 위한 유틸리티를 제공합니다.
///!
//! # 예시
//!
//! ```
//! let config = my_crate::config::parse("config.toml");
//! assert!(config.is_ok());
//! ```
pub fn parse(file_path: &str) -> Result<Config, ParseError> {
// 구현 내용
}
내부 문서 주석은 모듈 수준이나 크레이트 수준의 문서화에 일반적으로 사용됩니다. lib.rs
파일의 시작 부분에 위치하면 전체 크레이트를 문서화하고 생성된 문서의 첫 페이지를 형성합니다.
이 주석 스타일 간의 기술적인 차이는 미세하지만 중요합니다: ///
는 그 뒤에 오는 내용을 문서화하고, //!
는 그것을 포함하는 내용을 문서화합니다.
Rustdoc의 Markdown 지원
Rustdoc은 몇 가지 확장 기능이 있는 CommonMark 호환 Markdown 파서를 사용합니다. 이는 문서 작성자가 풍부한 서식 옵션에 액세스할 수 있도록 합니다:
기본 서식
/// # 제목 수준 1
/// ## 제목 수준 2
///
/// 단락은 빈 줄로 구분됩니다.
///
/// *기울임 텍스트* 및 **굵은 텍스트**를 지원합니다.
///
/// - 비정렬 목록
/// - 만들어질 수 있습니다
/// - 이렇게
///
/// 1. 정렬 목록
/// 2. 잘 작동합니다
///
/// `인라인 코드`는 백틱으로 둘러싸입니다.
코드 블록
코드 블록은 Rustdoc에서 특히 중요하며, 두 가지 용도로 사용됩니다: 문서에서 코드 예제를 표시하고 테스트로 추출될 수 있습니다.
/// ```rust
/// // 이것은 코드 블록입니다
/// let x = 5;
/// assert_eq!(x, 5);
/// ```
기본적으로, 시작하는 세 개의 백틱 뒤에 언어가 명시되지 않으면 Rustdoc은 코드 블록이 Rust 코드라고 가정합니다. 하지만, 구문 강조를 위해 다른 언어를 지정할 수 있습니다:
/// ```json
/// {
/// "name": "example",
/// "version": "1.0.0"
/// }
/// ```
Rustdoc 확장 기능
Rustdoc은 여러 추가 기능으로 CommonMark을 확장합니다:
취소선 텍스트
/// ~~취소선 텍스트~~는 물결표를 사용합니다.
각주
/// 이 진술은 명확한 설명이 필요합니다[^1].
///
/// [^1]: 여기에서 설명이 있습니다.
표
/// | 헤더1 | 헤더2 |
/// |---------|---------|
/// | 셀1 | 셀2 |
/// | 셀3 | 셀4 |
작업 목록
/// - [x] 완료된 작업
/// - [ ] 미완료 작업
스마트 구두점
Rustdoc은 ASCII 구두점 시퀀스를 자동으로 Unicode 등가물로 변환합니다:
--
는 en 대시 (–)로 변환됩니다.---
는 em 대시 (—)로 변환됩니다....
는 생략 기호 (…)로 변환됩니다.- 직접 인용은 곱슬 인용으로 변환됩니다.
자세한 Rustdoc 명령줄 인터페이스
Rustdoc은 문서 생성 맞춤화를 위해 포괄적인 명령줄 옵션 세트를 제공합니다:
$ rustdoc --help
가장 기술적으로 중요한 옵션 중 일부는 다음과 같습니다:
--document-private-items
: 기본적으로 Rustdoc은 공개 항목만 문서화합니다. 이 플래그는 내부 문서화를 위해 비공식 항목을 문서화합니다.--test
: 문서 예제를 테스트로 실행하여 컴파일 및 실행되는지 확인합니다.--test-args
:--nocapture
와 같은 추가 인수를 테스트 런너에 전달하여 테스트에서 출력을 표시합니다.--edition=EDITION
: 코드를 구문 분석하고 실행하기 위한 Rust 버전을 지정합니다 (2015, 2018, 2021, 2024).--target=TARGET
: 지정된 대상 플랫폼에 대해 문서를 생성합니다.--crate-type=TYPE
: 테스트에 대한 크레이트 유형을 지정합니다 (bin, lib, rlib, dylib, cdylib, staticlib, proc-macro).-L FLAG=PATH
: 테스트에서 종속성을 해결하는 데 중요한 라이브러리 검색 경로에 디렉터리를 추가합니다.--cfg=SPEC
: 문서 코드에서 조건부 컴파일을 활성화하기 위해 컴파일러에--cfg
플래그를 전달합니다.--extern NAME=PATH
: 외부 크레이트의 위치를 지정하여 테스트가 외부 종속성을 참조할 수 있게 합니다.
외부 종속성이 있는 프로젝트에서, 일반적인 Rustdoc 호출은 다음과 같을 수 있습니다:
$ rustdoc src/lib.rs --crate-name example_crate \
--edition=2021 \
-L dependency=target/debug/deps \
--extern serde=target/debug/deps/libserde-abcd1234.rlib \
--extern tokio=target/debug/deps/libtokio-efgh5678.rlib
다행히도 Cargo는 간단한 명령으로 이 복잡한 프로세스를 자동화합니다:
$ cargo doc --document-private-items
Cargo와의 통합
Cargo는 cargo doc
명령을 통해 Rustdoc을 쉽게 사용할 수 있는 인터페이스를 제공합니다. 내부적으로 Cargo는 적절한 매개변수로 Rustdoc을 호출합니다:
$ cargo doc --verbose
이 명령을 실행하면 실제 Rustdoc 호출이 표시되며, Cargo가 경로를 어떻게 구성하는지 볼 수 있습니다.
핵심 기능은 다음을 포함합니다:
cargo doc
: 현재 크레이트 및 해당 종속성에 대한 문서를 생성합니다.cargo doc --no-deps
: 현재 크레이트에 대해서만 문서를 생성합니다.cargo doc --open
: 문서를 생성하고 웹 브라우저에서 엽니다.cargo doc --document-private-items
: 문서에 비공식 항목을 포함합니다.cargo test --doc
: 문서 테스트를 실행합니다.
Cargo는 Cargo.toml
파일에서 크레이트 이름을 현재 설정하고, target/doc/
아래에 올바른 출력 디렉토리 구조를 설정하며, 모든 종속성이 적절하게 연결되도록 보장합니다.
문서 구조 및 조직
크레이트 수준 문서화
크레이트 수준의 문서는 라이브러리의 랜딩 페이지 역할을 하며 포괄적인 개요를 제공해야 합니다. 이는 lib.rs
파일 상단에 내부 문서(//!
)로 작성됩니다:
//! # 나의 고급 암호화 라이브러리
//!
//! 이 크레이트는 다음에 초점을 맞춘 암호화 원시 기능을 제공합니다:
//!
//! - **성능**: 최신 CPU에 맞춰 최적화된 구현
//! - **보안**: 정식으로 검증된 알고리즘
//! - **사용성**: 높은 수준의 오용하기 어려운 API
//!
//! ## 빠른 시작
//!
//! ```rust
//! use crypto_lib::{Cipher, Mode};
//!
//! let key = crypto_lib::generate_key(256);
//! let cipher = Cipher::new(&key, Mode::GCM);
//!
//! let plaintext = b"비밀 메시지";
//! let ciphertext = cipher.encrypt(plaintext);
//! ```
//!
//! ## 기능
//!
//! 이 크레이트는 다음 알고리즘을 지원합니다:
//!
//! - AES (128, 192, 256)
//! - ChaCha20
//! - Poly1305
//! - HMAC
//! - PBKDF2
효과적인 크레이트 수준 문서는 일반적으로 다음을 포함합니다:
- 크레이트 목적에 대한 간결한 1문장 설명
- 핵심 개념 및 기능에 대한 자세한 설명
- 기본 사용법을 보여주는 빠른 시작 예제
- 더 복잡한 라이브러리에 대한 아키텍처 개요
- 기능 플래그 및 구성 옵션
- 호환성 정보
- 성능 특성
모듈 수준 문서화
모듈은 Rust에서 조직 단위로 작용하며이며 그들의 목적과 내용을 설명하는 자체 문서가 있어야 합니다:
pub mod symmetric {
//! 대칭 암호화 알고리즘입니다.
//!
//! 이 모듈은 블록 및 스트림 암호, 인증된 암호화 알고리즘 및 관련 유틸리티의 구현을 제공합니다.
//!
//! # 보안 고려사항
//!
//! 모든 구현은 [보안 회사]에 의해 감사되었으며,
//! [검증 도구]를 사용하여 공식적으로 검증되었습니다.
/// 128, 192 및 256 비트 키를 지원하는 AES 블록 암호 구현입니다.
pub struct Aes {
// 필드 여기
}
// 더 많은 항목...
}
항목 수준 문서화
구조체, 함수 및 특성과 같은 개별 항목은 그들의 목적, 사용법 및 특별한 고려 사항을 설명하는 집중된 문서를 가져야 합니다:
/// 암호학적으로 안전한 난수 생성기입니다.
///
/// 이 CSPRNG는 시스템의 엔트로피 소스를 사용하여
/// 암호 작업에 적합한 난수를 생성합니다.
///
/// # 예시
///
/// ```
/// use crypto_lib::CSPRNG;
///
/// let mut rng = CSPRNG::new();
/// let random_bytes = rng.generate_bytes(32);
/// ```
///
/// # 보안
///
/// Linux에서는 사용 가능한 경우 getrandom(2)를 사용하고,
/// /dev/urandom으로 대체합니다.
/// Windows에서는 BCryptGenRandom을 사용합니다.
/// macOS에서는 SecRandomCopyBytes를 사용합니다.
pub struct CSPRNG {
// 구현 세부사항
}
impl CSPRNG {
/// 암호학적으로 안전한 난수 생성기를 생성합니다.
///
/// # 패닉
///
/// 시스템의 엔트로피 소스가 사용 불가능할 경우 패닉이 발생합니다.
///
/// # 예시
///
/// ```
/// let rng = crypto_lib::CSPRNG::new();
/// ```
pub fn new() -> Self {
// 구현
}
/// 지정된 수의 난수를 생성합니다.
///
/// # 인자
///
/// * `len` - 생성할 난수의 수
///
/// # 반환값
///
/// `len` 개의 암호학적으로 안전한 난수 바이트를 포함하는 벡터입니다.
///
/// # 예시
///
/// ```
/// use crypto_lib::CSPRNG;
///
/// let mut rng = CSPRNG::new();
/// let key_material = rng.generate_bytes(32);
/// assert_eq!(key_material.len(), 32);
/// ```
pub fn generate_bytes(&mut self, len: usize) -> Vec<u8> {
// 구현
}
}
문서 테스트 심층 분석
Rustdoc의 가장 강력한 기능 중 하나는 코드 예제를 테스트로 실행할 수 있는 능력입니다. 이는 다음을 보장합니다:
- 문서의 예제가 실제로 컴파일됨
- 예제가 예상된 결과를 생성함
- 예제가 API가 발전함에 따라 최신 상태로 유지됨
문서에 Rust 코드 블록을 포함하면 Rustdoc은 이를 추출하고 그 주위에 테스트 하네스를 생성합니다:
/// 두 숫자를 더합니다.
///
/// # 예시
///
/// ```
/// let result = my_crate::add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
비하인드 스토리로 Rustdoc은 이를 독립적인 테스트 파일로 변환하여 다음과 비슷한 형태로 만듭니다:
extern crate my_crate;
fn main() {
let result = my_crate::add(2, 3);
assert_eq!(result, 5);
}
이 파일은 컴파일되고 실행됩니다. 프로그램이 패닉 없이 컴파일되고 실행되면 테스트가 통과합니다.
테스트 전처리
Rustdoc은 테스트를 실행하기 전에 간단한 예제를 더 편리하게 만들기 위해 여러 변환을 적용합니다:
- 일반적인 린트(예:
unused_variables
및dead_code
)를 허용합니다. - 예제에
extern crate
가 포함되어 있지 않고#![doc(test(no_crate_inject))]
가 지정되지 않은 경우,extern crate <mycrate>;
를 삽입합니다. - 예제에
fn main
이 포함되어 있지 않은 경우, 코드는fn main() { ... }
로 감싸집니다.
이러한 변환을 통해 여러분은 보일러플레이트 없이 예제의 중요한 부분에 집중할 수 있습니다.
테스트 동작 제어
Rustdoc은 테스트 실행 방식을 제어할 수 있는 여러 속성을 제공합니다:
ignore
: 코드가 테스트되지 않음should_panic
: 코드는 컴파일되어야 하지만 실행 시 패닉이 발생해야 함compile_fail
: 코드는 컴파일되어서는 안됨no_run
: 코드는 컴파일되지만 실행되지 않음edition2015
,edition2018
,edition2021
: 특정 Rust 버전으로 코드를 실행함
예시:
/// ```ignore
/// // 이 코드는 테스트되지 않습니다
/// let x = function_that_doesnt_exist();
/// ```
///
/// ```should_panic
/// // 이 코드는 패닉이 발생해야 합니다
/// panic!("이 예제는 패닉을 보여줍니다");
/// ```
///
/// ```compile_fail
/// // 이 코드는 컴파일되어서는 안 됩니다
/// let x: i32 = "이 코드는 컴파일되지 않아야 합니다";
/// ```
///
/// ```no_run
/// // 이 코드는 컴파일되지만 실행되지 않습니다
/// loop {
/// println!("이 코드는 영원히 실행될 것입니다!");
/// }
/// ```
///
/// ```edition2021
/// // 이 코드는 Rust 2021 기능을 사용합니다
/// let result = try {
/// "10".parse::<i32>()?
/// };
/// ```
문서 테스트에서 ?
사용하기
문서 예제가 main()
함수로 포장되어 ()
를 반환하므로 ?
연산자를 사용하는 데는 특별한 처리가 필요합니다. 두 가지 접근 방식이 있습니다:
- 결과를 반환하는
main
함수를 명시적으로 정의:
/// ```
/// # fn main() -> Result<(), std::io::Error> {
/// let content = std::fs::read_to_string("file.txt")?;
/// println!("파일 내용: {}", content);
/// # Ok(())
/// # }
/// ```
2. Ok(())
와 함께 타입 주석 사용:
/// ```
/// let content = std::fs::read_to_string("file.txt")?;
/// println!("파일 내용: {}", content);
/// # Ok::<(), std::io::Error>(())
/// ```
두 경우 모두, 일부 줄의 시작 부분의 #
는 렌더링된 문서에서 숨겨지지만 테스트에는 포함됩니다.
항목에 이름으로 링크하기
Rustdoc은 문서 작성자가 코드베이스의 다른 항목에 링크를 생성할 수 있는 강력한 교차 참조 시스템을 제공합니다. 이 기능은 문서의 탐색 가능성을 크게 향상시킵니다.
문서 내 링크
다른 항목에 링크를 생성하려면 구문 [
item_name]
을 사용합니다:
/// 표준 라이브러리의 [`HashMap`] 유형을 사용합니다.
///
/// 또한 이 크레이트의 다른 곳에 정의된 [`build_map`] 함수에 의존합니다.
pub fn process_data() {
// 구현
}
/// 미리 정의된 값으로 새로운 [`HashMap`]을 생성합니다.
pub fn build_map() -> HashMap<String, i32> {
// 구현
}
Rustdoc이 이러한 링크를 처리할 때 자동으로 올바른 항목으로 해결하여 생성된 HTML에서 클릭 가능한 하이퍼링크를 생성합니다.
경로 지정
특히 서로 다른 모듈에서 동일한 이름을 가진 항목을 다룰 때, 보다 정확한 링크를 위해 전체 경로를 사용할 수 있습니다:
/// 이 함수는 저장을 위해 [`std::collections::HashMap`]을 사용하고,
/// 출력을 형식화하기 위해 [`crate::utils::format`]을 사용합니다.
pub fn complex_operation() {
// 구현
}
경로 해결은 Rust의 가시성 규칙을 따르므로 현재 범위에서 볼 수 있는 항목에만 링크할 수 있습니다.
링크 대상
다양한 종류의 항목에 링크할 수 있습니다:
/// 구조체 링크: [`MyStruct`]
/// 열거형 링크: [`Option`]
/// 특성 링크: [`Iterator`]
/// 함수 링크: [`process_data`]
/// 메서드 링크: [`MyStruct::new`]
/// 모듈 링크: [`crate::utils`]
/// 상수 링크: [`MAX_SIZE`]
/// 타입 별칭 링크: [`Result`]
이 포괄적인 링크 시스템은 문서 작성자가 복잡한 API를 탐색하는 데 도움이 되는 상호 연결된 문서의 풍부한 웹을 생성할 수 있도록 합니다.
고급 문서 기능
#[doc]
속성
#[doc]
속성은 문서 생성에 대한 고급 제어를 제공합니다:
// /// 주석 사용과 동일합니다
#[doc = "아래 항목에 대한 문서입니다."]
pub struct DocumentedStruct;
// 문서에서 항목 숨기기
#[doc(hidden)]
pub struct InternalStruct;
// 검색 별칭 추가
#[doc(alias = "connection")]
#[doc(alias = "socket")]
pub struct NetworkStream;
기능 플래그를 기반으로 조건부 문서화:
/// 이 함수는 놀라운 작업을 수행합니다.
#[doc = "기본 기능 설명."]
#[cfg_attr(feature = "advanced", doc = "고급 모드가 활성화되면 고급 모드도 지원합니다.")]
pub fn do_things() {
// 구현
}
문서 포함 패턴
문서에서 콘텐츠 재사용:
/// # 안전
///
#[doc = include_str!("../docs/common_safety_notes.md")]
pub unsafe fn perform_unsafe_operation() {
// 구현
}
이를 통해 별도의 파일에 공통 문서 세그먼트를 유지하고 필요에 따라 포함하여 중복을 줄이고 일관성을 확보할 수 있습니다.
스크랩된 예제
Rustdoc은 크레이트의 테스트 및 예제 디렉터리에서 코드 예제를 자동으로 추출하여 API 사용에 대한 추가 컨텍스트를 제공할 수 있습니다:
$ cargo doc --document-scraped-examples
이 기능은 공개 항목의 사용을 찾아내어 이러한 사용을 예제로 추출하는 방식으로 작동합니다. 인라인 문서 예제가 충분하지 않을 수 있는 복잡한 API에 특히 유용합니다.
조건부 문서화
여러분은 cfg
속성을 사용하여 조건부로 문서를 포함하거나 제외할 수 있습니다:
#[cfg(target_os = "windows")]
/// Windows 전용 구현 세부사항입니다.
pub fn windows_only_function() {
// Windows 구현
}
#[cfg(target_os = "linux")]
/// Linux 전용 구현 세부사항입니다.
pub fn linux_only_function() {
// Linux 구현
}
이를 통해 관련될 때만 나타나는 플랫폼 전용 또는 기능 전용 문서를 생성할 수 있습니다.
문서의 사용자 정의 HTML
특별한 서식 요구 사항에 따라 Rustdoc은 문서에 HTML을 직접 포함하도록 허용합니다:
/// <div class="warning">
/// <strong>경고:</strong> 이 함수는 I/O를 수행하며 차단될 수 있습니다.
/// </div>
pub fn blocking_operation() {
// 구현
}
사용자 지정 CSS와 결합하면 Markdown만으로 제공되는 서식을 넘어선 풍부한 서식을 가능하게 합니다.
사용자 정의 HTML 및 CSS
Rustdoc은 생성된 문서의 모양을 HTML 및 CSS를 통해 사용자 정의할 수 있도록 허용합니다:
HTML 전처리
문서 헤더에 사용자 정의 HTML을 추가할 수 있습니다:
$ rustdoc src/lib.rs --html-in-header custom-header.html
이것은 사용자 정의 스타일시트, JavaScript 라이브러리 또는 메타 태그를 추가하는 데 유용합니다.
CSS 사용자 정의
문서에 사용자 정의 CSS를 적용하려면:
$ rustdoc src/lib.rs --css custom-styles.css
여러분의 CSS 파일은 Rustdoc의 HTML 구조를 대상으로 하여 색상, 글꼴, 레이아웃 등을 사용자 정의할 수 있습니다:
/* 기본 배경 색상 변경 */
body {
background-color: #f5f5f5;
}
/* 경고 블록 스타일 */
.warning {
background-color: #fff3cd;
border-left: 4px solid #ffc107;
padding: 0.5rem 1rem;
margin: 1rem 0;
}
/* 코드 블록에 대한 사용자 정의 스타일 */
pre {
background-color: #282c34;
border-radius: 6px;
padding: 1rem;
}
사용자 정의 렌더링 테마
Rustdoc은 Light, Rust, Coal, Navy 및 Ayu를 포함한 여러 내장 테마를 지원합니다. 사용자 정의 테마를 생성할 수도 있습니다:
$ rustdoc src/lib.rs --theme mytheme.css
문서화 모범 사례
기술적 정확성
문서는 기술적으로 정확해야 합니다. 정확한 동작, 에지 케이스 및 성능 특성을 지정합니다:
/// 이진 검색을 사용하여 정렬된 슬라이스에서 요소를 찾습니다.
///
/// # 복잡도
///
/// 시간 복잡도: O(log n)
/// 공간 복잡도: O(1)
///
/// # 패닉
///
/// 슬라이스가 오름차순으로 정렬되지 않은 경우 패닉이 발생합니다.
///
/// # 예시
///
/// ```
/// let sorted = [1, 2, 3, 4, 5];
/// assert_eq!(my_crate::binary_search(&sorted, 3), Some(2));
/// assert_eq!(my_crate::binary_search(&sorted, 6), None);
/// ```
pub fn binary_search<T: Ord>(slice: &[T], value: T) -> Option<usize> {
// 구현
}
구조화된 문서화
각 항목 유형에 대해 일관된 구조를 따릅니다:
함수 및 메서드:
- 짧은 설명
- 매개변수 설명
- 반환 값 설명
- 오류 케이스
- 패닉 섹션 (해당하는 경우)
- 예시
- 성능 특성
- 안전 고려 사항 (unsafe 함수의 경우)
구조체 및 열거형:
- 목적 및 높은 수준의 설명
- 필드/변형 설명
- 생성 메서드
- 일반적인 작업
- 일반적인 사용 예
특성:
- 계약 및 보장
- 필요한 메서드 설명
- 제공된 메서드 문서화
- 구현 안내
- 구현 및 사용 예시
언어의 정확성
정확한 기술 언어를 사용하고 모호함을 피합니다:
- “빠르다” 대신 “O(log n) 시간 복잡도”를 지정합니다.
- “메모리 효율적” 대신 “상수 스택 공간 사용”을 지정합니다.
- “실패할 수도 있다” 대신 정확한 오류 조건을 지정합니다.
- “큰 입력” 대신 구체적인 한계를 지정합니다.
버전 정보
API 안정성과 버전 관리 고려 사항을 문서화합니다:
/// RFC 1234에 따라 네트워크 패킷을 처리합니다.
///
/// # 안정성
///
/// 이 함수는 0.2.0 버전 이후 안정적이라고 간주됩니다.
///
/// # 버전 차이
///
/// 0.3.0 이전에는 이 함수가 1500바이트보다 큰 패킷을 조용히 잘라내었습니다.
/// 이제는 오류를 반환합니다.
pub fn process_packet(packet: &[u8]) -> Result<ProcessedPacket, PacketError> {
// 구현
}
고급 테스트 기술
다양한 환경에서 테스트
특정 환경 변수를 사용하여 문서 테스트를 실행하도록 구성할 수 있습니다:
/// ```
/// # std::env::set_var("API_KEY", "test_key");
/// let client = my_crate::Client::new_from_env()?;
/// # Ok::<(), my_crate::Error>(())
/// ```
외부 리소스와의 테스트
외부 리소스가 필요한 테스트에는 no_run
속성을 사용하고 요구 사항을 설명합니다:
/// ```no_run
/// // 이 예제는 localhost:5432에 PostgreSQL 데이터베이스가 필요합니다.
/// // 사용자 이름: "test" 및 비밀번호: "test"
/// let db = my_crate::Database::connect(
/// "postgres://test:test@localhost:5432/testdb"
/// )?;
/// # Ok::<(), my_crate::Error>(())
/// ```
오류 처리 테스트
API에서 오류가 처리되는 방식을 보여줍니다:
/// ```
/// use my_crate::{process_data, DataError};
///
/// // 성공 사례
/// let result = process_data(&[1, 2, 3]);
/// assert!(result.is_ok());
///
/// // 오류 사례
/// let error_result = process_data(&[]);
/// assert!(matches!(error_result, Err(DataError::EmptyInput)));
/// ```
국제화 및 접근성
비영어 문서
Rustdoc에는 내장된 국제화 지원이 없지만 기능 플래그를 사용하여 여러 언어로 문서를 제공할 수 있습니다:
#[cfg(feature = "docs-en")]
/// 두 숫자를 더합니다.
#[cfg(feature = "docs-es")]
/// Suma dos números.
#[cfg(feature = "docs-ja")]
/// 二つの数値を足します。
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
접근성 고려 사항
장애가 있는 사용자가 접근할 수 있도록 문서를 작성하십시오:
- 이미지에 대한 텍스트 대체 제공
- 충분한 색 대비 사용
- 적절한 제목으로 콘텐츠 구조화
- 코드 예제를 스크린 리더 친화적으로 만들기
/// 아래 아키텍처 다이어그램은 시스템 구성 요소를 설명합니다:
///
/// 
/// *대체 텍스트: 입력에서 처리 및 출력으로 데이터 흐름을 보여주는 플로우차트,
/// 양쪽에 데이터베이스 및 캐시 구성 요소가 있습니다.*
결론
Rustdoc은 모든 프로그래밍 언어 생태계에서 가장 강력하고 포괄적인 문서 도구 중 하나로 자리잡고 있습니다. Rust 컴파일러와의 긴밀한 통합, 강력한 테스트 기능 및 풍부한 형식 옵션은 개발자가 설명적일 뿐만 아니라 정확하고 사용 가능하며 유지 관리 가능한 문서를 작성할 수 있게 해줍니다.
Rustdoc의 모든 기능을 활용하면 Rust 개발자는 학습 자료이자 신뢰할 수 있는 참고 자료로서의 역할을 하는 문서를 생성할 수 있습니다. 문서는 API 설계 및 소프트웨어 사용성의 기본 요소입니다. Rustdoc의 기능을 사용하여 세심하게 작성하면 문서는 학습 곡선을 줄이고 오류를 예방하며 라이브러리의 올바른 사용을 촉진하는 귀중한 자산이 됩니다.
Rust 생태계가 계속 발전함에 따라 Rustdoc도 함께 발전하고 있으며, 점점 더 다양하고 정교한 사용자 기반의 요구를 충족하기 위해 지속적으로 기능을 향상시키고 있습니다. Rustdoc을 마스터하면 자신의 코드베이스를 개선할 뿐만 아니라 Rust 커뮤니티가 프로그래밍 세계에서 가장 환영받고 접근하기 쉬운 커뮤니티 중 하나가 되는 데 기여할 수 있습니다.
자주 묻는 질문
1. 실패하는 문서 테스트를 디버깅하려면 어떻게 해야 하나요?
답변: 문서 테스트는 여러 기술을 사용하여 디버깅할 수 있습니다:
출력이 더 많은 테스트를 실행합니다:
cargo test --doc -- --nocapture
테스트에 print 문을 추가합니다 (문서에는 숨겨지지만 테스트 실행 시 표시됩니다):
/// ```
/// let result = my_crate::complex_function();
/// # println!("디버그: result = {:?}", result);
/// assert!(result.is_ok());
/// ```
-test-args
플래그를 사용하여 추가 옵션을 전달합니다:
cargo test --doc -- --test-args=--show-output
테스트를 더 쉽게 디버깅하기 위해 별도의 파일에 테스트의 독립적인 복제를 만듭니다.
테스트에 영향을 미칠 수 있는 기능 플래그를 사용하고 있다면 활성화되어 있는지 확인합니다:
cargo test --doc --features=my-feature
2. 안전하지 않은 코드를 올바르게 문서화하려면 어떻게 해야 하나요?
답변: 안전하지 않은 코드를 문서화할 때 안전 요구 사항에 특별한 주의를 기울여야 합니다:
- 호출자가 유지해야 할 모든 불변량을 명확하게 명시하는 "안전" 섹션을 항상 포함합니다.
- 안전 요구 사항이 충족되지 않을 경우 발생할 수 있는 정의되지 않은 동작을 자세히 설명합니다.
- 함수가 왜 안전하지 않아야 하는지 설명합니다.
- 올바른 사용과 잘못된 사용을 보여주는 예제를 제공합니다 (후자는
compile_fail
를 사용합니다).
예시:
/// 원시 포인터를 역참조합니다.
///
/// # 안전
///
/// 호출자는 다음을 보장해야 합니다.
/// - 포인터가 유형 T에 대해 올바르게 정렬되어야 합니다.
/// - 포인터가 T의 초기화된 인스턴스를 가리키고 있어야 합니다.
/// - 포인터가 T의 크기만큼 읽기 유효해야 합니다.
/// - 이 함수가 실행되는 동안 동일한 메모리에 대한 다른 참조가 없어야 합니다.
///
/// 이러한 조건을 위반하는 경우 정의되지 않은 동작이 발생합니다.
///
/// # 예시
///
/// 안전한 사용:
/// ```
/// let value = 42;
/// let ptr = &value as *const i32;
/// unsafe {
/// assert_eq!(my_crate::deref(ptr), 42);
/// }
/// ```
///
/// ```compile_fail
/// // 이는 정의되지 않은 동작