Rust에서 WIP 코드를 경고로 남기기
6 hours ago
4
- Rust 개발 중 모든 오류 경로와 소유권 문제를 즉시 정리하면 구현 흐름이 끊기기 쉬워, happy path를 먼저 만들고 남은 일을 경고로 추적하는 전략이 유용함
- 표준 Rust만으로도 unwrap, clone, todo!, 기본 컴파일러 경고, /// 문서 주석 트릭을 조합해 미완성 코드를 표시할 수 있음
- 기존 방식은 unwrap과 clone이 경고를 내지 않고, todo!도 간접 경고에 의존하며, /// 트릭은 위치에 따라 컴파일 오류나 의도치 않은 문서화로 이어질 수 있음
- wip crate는 wip!, unwrap_wip, clone_wip, fixme!를 통해 임시 구현, 임시 unwrap/clone, 나중에 고칠 메모를 항상 경고로 드러냄
- Meilisearch는 CI에서 -D warning으로 경고를 오류로 바꿔 WIP 코드 유입을 막고, 개발 중 추가한 wip 의존성은 리뷰 전 히스토리 정리 과정에서 제거하는 흐름을 사용함
Rust 개발 중 경고가 필요한 이유
- Rust는 정확성을 중시하는 언어지만, 개발 도중 모든 오류 경로를 바로 처리하면 구현 속도와 집중이 떨어질 수 있음
- rustc가 Result 반환, 오류 처리, 엣지 케이스 구현 같은 이유로 컴파일을 막을 때 보통 두 선택지가 생김
- 즉시 완전한 오류 처리를 구현하고, PR 준비 전까지 여러 번 리팩터링함
- TODO later 성격의 표시를 남겨 문제를 경고 수준으로 낮추고 현재 작업을 이어감
- 경고는 개발을 막지 않으면서도 PR 병합 전 정리해야 할 신호로 남음
- Meilisearch는 CI에서 컴파일러를 -D warning 플래그로 실행해 모든 경고를 오류로 바꾸며, WIP 코드가 실수로 배포되지 않도록 함
- 코드 리뷰는 버그를 막고 팀 내 지식을 공유하는 기본 관행이지만, 사람의 기억과 주의력에만 의존하면 결국 실수가 생길 수 있어 추가 가드레일이 필요함
표준 Rust로 미완성 처리를 미루는 방법
-
unwrap으로 오류 처리 미루기
- Result나 Option에 unwrap을 사용하면 오류 경로에서 panic이 발생하는 대가로 내부 값을 꺼내 현재 구현을 계속할 수 있음
- 나머지 코드가 준비된 뒤 임시로 추가한 unwrap을 골라 제거하고 적절한 오류 처리로 바꿀 수 있음
- 이 방식은 Rust가 오류를 올바르게 다룰 구조를 제공하더라도, 그 처리를 즉시 끝낼 필요는 없다는 전제에 기반함
-
clone으로 소유권 문제 미루기
- 소유권 문제는 오류 처리보다 덜 흔하지만, 올바른 소유권 유지가 설계 변경을 요구할 수 있음
- 이때 값을 이동시키는 대신 clone해 생명주기 문제를 임시로 피할 수 있음
- 나중에 적절한 변수를 더 상위 스택으로 전달하는 방식으로 clone을 제거할 수 있는 경우를 경험적으로 식별할 수 있음
- 다만 수정이 코드 구조 변경으로 이어질 수 있어, 오류 처리보다 미루기가 더 까다로움
-
todo!()로 구현 자리만 확보하기
- Rust 표준 라이브러리의 todo!() 매크로는 미완성 코드를 나타내며, 프로토타이핑 중 타입 분석을 통과시키기 위한 자리표시자로 유용함
- todo!()는 panic으로 diverge하기 때문에 대부분의 타입 위치에서 자리표시자 표현식으로 사용할 수 있음
- 인터페이스를 잡는 중 함수 정의를 사용할 수 있게 하면서 실제 구현은 뒤로 미룰 수 있음
- todo!()는 프로그램 사용자에게 기능 미구현을 알리기보다, 코드 작성자와 리뷰어를 위한 WIP 편의 기능에 가까움
- 사용자에게 기능 미구현 상태를 알리는 용도에는 unimplemented!() 매크로가 따로 있음
-
기본 컴파일러 경고와 문서 주석 트릭
- Rust 컴파일러의 기본 경고도 개발 중 미완성 상태를 드러내는 데 유용함
- 사용하지 않는 바인딩
- 불필요한 mut
- 사용하지 않은 Result와 Option
- 개발 중 이런 경고를 _ 접두사나 다른 트릭으로 임시 제거하면 미완성 코드가 그대로 넘어갈 위험이 있음
- 타입 시스템으로 추적되지 않는 엣지 케이스나 깨진 로직은 주석으로 남기는 경우가 있음
- /// 문서 주석처럼 보이게 주석을 달면, Rust가 문서화 대상이 없는 문서 주석에 대해 경고를 내므로 해당 위치의 문제를 경고로 추적할 수 있음
표준 방식의 한계
- 가장 큰 문제는 모든 기법이 해결해야 할 문제와 연결된 경고를 안정적으로 만들지 못한다는 점임
- todo!()는 자주 경고를 유발하지만, 함수 인자가 사용되지 않거나 필요한 mutation이 일어나지 않는 등 간접 원인에서 나오는 경우가 많음
- unwrap과 clone은 경고를 전혀 내지 않으므로, 최종 PR 전에 다시 읽으며 제거해야 함
- unwrap은 정상적으로 프로덕션에 남을 수도 있어, 임시 WIP 용도와 일반 용도가 섞일 수 있음
- /// 문서 주석 트릭은 해킹에 가까우며, 표현식 위치에서는 문서 주석이 금지되어 컴파일 오류가 날 수 있음
- 실제로 문서화가 되는 위치에 ///를 쓰면 기대한 경고가 나오지 않고, 배포 코드에 원치 않는 문서가 남을 수 있음
wip crate가 제공하는 도구
- wip crate는 Rust 개발 중 “나중에 처리할 경고” 전략을 더 편하게 만들기 위한 도구 모음임
- 일반 crate처럼 추가할 수 있음
- 필요한 파일에서는 prelude를 가져올 수 있음
- wip는 Rust의 deprecation warning에 의존하므로, 에디터가 deprecated 함수 호출에 취소선을 긋는 기능은 끄는 편이 덜 거슬릴 수 있음
-
wip::wip!
- wip! 매크로는 todo!처럼 동작하지만, 사용할 때 항상 경고를 냄
- 미완성 코드를 표시하기 위해 todo!를 쓰던 위치에 사용할 수 있음
- 초기 버전에서는 todo라는 이름을 썼지만, 의존성이 std 매크로를 shadow하려 할 때 Rust가 이를 선호하지 않아 prelude 사용에 문제가 생겼음
-
unwrap_wip와 clone_wip
- unwrap_wip와 clone_wip는 Result와 Option에 대한 extension trait로 구현됨
- scope 안에 있으면 일반 unwrap, clone처럼 동작하지만 사용 시 경고를 냄
- 최종 코드에 unwrap이나 clone을 남기려는 의도가 아니라는 신호를 명확히 줄 수 있음
-
wip::fixme!
- fixme! 매크로는 wip!의 non-panicking 변형이며 표현식을 대신하지 않음
- TODO 주석처럼 쓸 수 있지만, /// 트릭 없이 안정적으로 경고를 생성함
- 나중에 고쳐야 할 메모를 남기는 용도로 자주 사용됨
사용 흐름과 주의점
- wip crate는 최근 몇몇 PR에서 사용됐고, 큰 PR 중 하나인 Meilisearch PR #6484에도 사용됨
- 일반적인 흐름은 개발 중 워크스페이스의 crate에 wip 의존성을 추가하고, 리뷰 전 히스토리를 다시 쓰는 과정에서 제거하는 방식임
- wip는 happy path에 집중하면서 나중에 처리할 일을 잊지 않게 해줌
- 단점도 있음
- fixme를 추가할 때 충분한 맥락을 쓰지 않으면 나중에 고치기 어려움
- 큰 PR에서는 wip가 만든 경고 수가 많아져 부담스러울 수 있음
- 현재 API는 docs.rs의 wip 문서에서 확인할 수 있음
-
Homepage
-
Tech blog
- Rust에서 WIP 코드를 경고로 남기기