소개
정상적으로 작동하는 코드는 다른 사람이 안전하게 유지 관리할 수 있는 프로젝트의 한 부분일 뿐입니다. 다른 사람에게 인계할 준비가 된 Rust 크레이트는 일관된 포맷을 사용하고, 문제가 의심되는 패턴을 피하며, 공개 인터페이스를 설명하고, 테스트를 통과하는 상태를 유지해야 합니다.
이 실습에서는 Rust의 표준 프로젝트 도구를 사용해 작은 라이브러리를 수정합니다. 먼저 rustfmt, Clippy, rustdoc을 하나씩 적용한 다음, 테스트 모음과 결합해 반복 가능한 품질 점검 루프를 구성합니다. 각 도구가 무엇을 검증하는지 집중할 수 있도록 코드는 의도적으로 작게 준비되어 있습니다.
소스 코드를 일관되게 포맷팅하기
이 단계에서는 rustfmt를 사용해 프로그램 동작은 바꾸지 않고 레이아웃 차이를 찾아 수정합니다.
준비된 라이브러리로 이동해 소스 파일을 엽니다.
cd /home/labex/project/handoff-helpers
nano src/lib.rs
첫 번째 함수는 유효한 Rust 코드이지만, 공백과 들여쓰기가 파일의 나머지 부분과 다릅니다. 포맷 규칙은 기계적으로 적용할 수 있으므로, 각 기여자가 직접 수정하는 것보다 도구를 사용하는 편이 일관성이 높습니다. 편집하지 말고 Ctrl+X를 누릅니다.
먼저 검사 모드를 사용합니다.
cargo fmt -- --check
이 명령은 실패하고 차이점을 diff로 표시해야 합니다. cargo fmt는 패키지의 Rust 파일을 선택합니다. 첫 번째 --는 Cargo 옵션의 끝을 나타내고, 두 번째 --check는 rustfmt에 전달됩니다. 검사 모드는 차이점을 보고하지만 파일을 다시 작성하지 않으므로 자동화된 검사에 유용합니다.
이제 포맷터를 적용합니다.
cargo fmt
소스 파일을 다시 엽니다.
nano src/lib.rs
이제 첫 번째 함수의 공백, 줄바꿈, 들여쓰기가 일관되게 정리되어 있습니다. 이름과 로직은 변경되지 않았습니다. nano를 종료한 다음 검사 모드가 아무 내용도 출력하지 않는지 확인합니다.
cargo fmt -- --check
출력이 없고 명령이 성공적으로 종료되면 모든 Rust 파일이 rustfmt 규칙과 일치한다는 뜻입니다.
Clippy 경고 수정하기
이 단계에서는 Clippy를 사용해 컴파일은 되지만 의도를 더 명확하게 표현할 수 있는 코드를 찾습니다.
Rust 컴파일러는 코드가 유효하고 타입 안전한지 검사합니다. Clippy는 문제가 의심되거나 불필요하게 복잡하거나 Rust답지 않은 패턴을 검사하는 lint를 추가합니다. 경고를 오류로 취급하도록 설정해 실행합니다.
cargo clippy -- -D warnings
첫 실행은 실패해야 합니다. rustfmt와 마찬가지로 --는 뒤에 오는 옵션을 기반 도구에 전달합니다. -D warnings는 **경고를 거부한다(deny warnings)**는 뜻이므로, 보고된 경고를 모두 수정할 때까지 품질 검사가 0이 아닌 상태 코드로 종료됩니다.
Clippy는 두 가지 개선 사항을 찾습니다. 길이를 0과 비교하는 대신 직접 빈 상태를 확인하는 메서드를 사용하고, 호출자가 Vec의 소유권을 갖도록 요구하는 대신 슬라이스를 받도록 수정해야 합니다. 소스 파일을 엽니다.
nano src/lib.rs
다음 코드를:
if cleaned.len() == 0 {
다음과 같이 변경합니다.
if cleaned.is_empty() {
그런 다음 open_count 매개변수를 다음 코드에서:
tasks: &Vec<bool>
다음과 같이 변경합니다.
tasks: &[bool]
is_empty()는 확인하려는 내용을 직접 표현합니다. 슬라이스는 구체적인 벡터 컨테이너를 불필요하게 요구하지 않고 빌린 시퀀스 데이터를 받을 수 있습니다. nano에서 저장하고 종료한 다음, 수정한 부분을 포맷하고 Clippy를 다시 실행합니다.
cargo fmt
cargo clippy -- -D warnings
경고 없이 마지막에 Finished 줄이 표시되면 더 엄격한 lint 정책에서도 라이브러리가 문제없이 컴파일되었다는 뜻입니다.
공개 인터페이스 문서화하기
이 단계에서는 문서화 주석을 추가하고 탐색할 수 있는 API 문서를 생성합니다.
///로 시작하는 주석은 바로 아래에 있는 항목을 문서화합니다. //!로 시작하는 주석은 주석이 속한 크레이트나 모듈을 설명합니다. rustdoc은 두 형식 모두를 링크가 포함된 HTML 문서로 변환합니다.
라이브러리 소스 파일을 엽니다.
nano src/lib.rs
파일 맨 위에 다음 두 줄을 추가합니다.
//! Small helpers for preparing task data for reports.
#![deny(missing_docs)]
이 내부 속성은 공개 항목에 문서가 없을 경우 빌드 오류가 발생하게 합니다. 문서화를 권장 사항이 아니라 명시적인 프로젝트 정책으로 만듭니다.
normalize_title 바로 위에 다음 주석을 추가합니다.
/// Returns a trimmed title, or `Untitled` when the input is blank.
open_count 바로 위에 다음 주석을 추가합니다.
/// Counts entries whose completion value is `false`.
nano에서 저장하고 종료합니다. 이 패키지만 대상으로 문서를 생성합니다.
cargo doc --no-deps
cargo doc은 rustdoc을 실행합니다. --no-deps 옵션은 의존성 크레이트의 문서 생성을 건너뛰므로 결과에 현재 패키지만 포함되고 더 빠르게 완료됩니다. 생성되는 시작 페이지는 target/doc/handoff_helpers/index.html입니다. Cargo는 Rust 크레이트 이름을 만들 때 패키지 이름의 하이픈을 밑줄로 변경합니다.
ls target/doc/handoff_helpers/index.html
해당 경로가 표시되면 rustdoc이 크레이트 페이지를 생성했고 누락된 문서 검사 정책도 통과했다는 뜻입니다.
전체 품질 점검 루프 실행하기
이 단계에서는 개별 도구를 예측 가능한 인계 전 점검 순서로 결합합니다.
포맷팅, 린팅, 문서화, 테스트는 서로 다른 질문에 답합니다.
- rustfmt는 소스가 표준 레이아웃을 따르는지 확인합니다.
- Clippy는 문제가 의심되거나 명확하지 않은 패턴이 남아 있는지 확인합니다.
- 테스트는 필요한 동작이 여전히 작동하는지 확인합니다.
- rustdoc은 프로젝트 정책에 따라 공개 인터페이스를 문서화할 수 있는지 확인합니다.
실패 원인을 명확한 한 가지 경계로 좁힐 수 있도록 각 검사를 따로 실행합니다. 먼저 포맷을 검사합니다.
cargo fmt -- --check
엄격한 lint 검사를 실행합니다.
cargo clippy -- -D warnings
라이브러리 테스트를 실행합니다.
cargo test
출력에 테스트 2개가 통과했다고 표시되어야 합니다. 마지막으로 필요한 문서를 다시 생성합니다.
cargo doc --no-deps
네 명령이 이 순서대로 모두 성공하면 크레이트가 일관되게 포맷되었고, lint를 통과했으며, 동작 테스트와 문서화도 완료된 상태입니다. 인계 전에 같은 루프를 실행하면 품질을 마지막에 눈으로 추측하는 대신 반복 가능한 증거로 확인할 수 있습니다.
요약
rustfmt로 포맷을 수정하고, 엄격한 Clippy 지적 사항을 해결했으며, 공개 라이브러리 인터페이스를 문서화하고, rustdoc 출력을 생성하고, 테스트가 통과하는 상태를 유지했습니다. 더 중요한 점은 이러한 도구를 반복 가능한 품질 점검 루프로 결합해 안정적인 프로젝트 인계를 지원할 수 있게 되었다는 것입니다.


