error-path-macros 0.1.0

Attribute macros for automatically attaching error paths to Result-returning Rust functions and impl blocks.
Documentation
# error-path-macros

**한국어** | [English]README.en.md

`error-path-macros``Result` 기반 Rust 함수와 `impl` 메서드에서 오류가 반환될 때 운영용 주소 조각을 자동으로 추가하는 절차적 속성 매크로 crate입니다. 주소는 호출 순서를 복원하는 stack trace가 아니라, 오류가 시스템의 어느 기능에 속하는지 나타내는 안정적인 식별자입니다.

```text
login.api.request_login
```

대부분의 애플리케이션은 이 crate를 직접 의존하지 않아도 됩니다. [`error-path`](https://crates.io/crates/error-path)의 `macros` feature가 같은 매크로를 재노출하며, 필요한 `WithErrorPath` trait과 adapter도 함께 제공합니다.

## 권장 설치

```toml
[dependencies]
error-path = { version = "0.1", features = ["macros"] }
```

## 직접 설치

매크로를 별도 crate에서 재노출하거나 의존성을 세밀하게 구성해야 한다면 core crate와 함께 설치합니다.

```toml
[dependencies]
error-path = "0.1"
error-path-macros = "0.1"
```

생성된 코드는 `::error_path::WithErrorPath`를 참조합니다. 따라서 core crate가 반드시 필요하며, 의존성 이름을 바꿨다면 `error_path`라는 이름으로 다시 노출해야 합니다. 최소 지원 Rust 버전은 1.77입니다.

## `#[error_path]`

단일 `Result` 반환 함수에 주소 조각을 붙입니다. 인자가 없으면 함수 이름을 사용하고, 문자열 인자가 있으면 그 값을 사용합니다. 경로 문자열 해석은 `error-path`의 현재 전역 구분자를 따릅니다.

```rust
use error_path::{ErrorPath, WithErrorPath};
use error_path_macros::error_path;

#[derive(Debug)]
struct ProfileError { path: ErrorPath }

impl WithErrorPath for ProfileError {
    fn with_error_path(mut self, path: &'static str) -> Self {
        self.path.prepend_path(path);
        self
    }
}

#[error_path]
fn load_profile() -> Result<(), ProfileError> {
    Err(ProfileError { path: ErrorPath::new() })
}

#[error_path("login.api")]
fn request_login() -> Result<(), ProfileError> {
    load_profile()
}

```

개념적으로 매크로는 원래 함수 본문을 실행한 뒤 다음과 같은 처리를 추가합니다.

```rust
result.map_err(|error| error_path::WithErrorPath::with_error_path(error, "login.api"))
```

동기와 `async` 함수 모두 지원하며, 원래 함수의 visibility와 signature는 유지합니다.

## `#[error_path_impl]`

`impl` 블록의 `Result` 반환 메서드에 `{base}.{method_name}` 주소를 붙입니다.

```rust
use error_path::{ErrorPath, WithErrorPath};
use error_path_macros::{error_path_impl, error_path_skip};

struct LoginApi;

#[error_path_impl("login.api")]
impl LoginApi {
    fn request_login(&self) -> Result<(), ProfileError> {
        Err(ProfileError { path: ErrorPath::new() })
    }

    #[error_path_skip]
    fn health_check(&self) -> Result<(), ProfileError> {
        Ok(())
    }
}

```

인자가 없을 때 base는 다음 규칙으로 정해집니다.

- trait implementation: trait 이름
- inherent implementation: 타입 이름

예를 들어 `impl LoginApi for LoginApiImpl`에 `#[error_path_impl]`을 붙이면 `LoginApi.request_login`이 생성됩니다. 별칭을 사용하고 싶다면 `#[error_path_impl("login.api")]`처럼 명시합니다.

## `#[error_path_skip]`

`#[error_path_impl]`이 붙은 블록에서 특정 메서드를 그대로 두고 싶을 때 사용합니다. 이 속성은 `#[error_path_impl]`이 소비하므로 단독으로 경로를 추가하지 않습니다.

## 오류 타입 호환성

매크로는 특정 에러 타입을 알지 못하며 `WithErrorPath` 하나만 호출합니다. 따라서 함수가 `Result<T, E>`를 반환하고 `E: WithErrorPath`이면 사용할 수 있습니다.

`error-path` core crate는 `ErrorPath`와 `anyhow`, `eyre`, `error-stack`, `stacked_errors`용 선택 adapter를 제공합니다. 자체 오류 타입이나 `thiserror`로 만든 타입도 `WithErrorPath`만 구현하면 호환됩니다.

## 제한사항

- `#[error_path]``Result` 반환 함수에만 적용해야 합니다. 다른 반환 타입에 적용하면 생성 코드가 `map_err`를 호출하므로 컴파일되지 않습니다.
- `#[error_path_impl]`은 반환 타입의 마지막 이름이 `Result`로 끝나는 메서드만 자동으로 감쌉니다.
- panic, thread, spawn 내부 오류는 자동 대상이 아닙니다. `Result`가 현재 함수 경계를 통해 반환될 때만 주소가 추가됩니다.
- 주소는 source file 경로나 runtime stack trace에서 추론되지 않습니다. 안정적인 문자열을 직접 제공하거나 함수·trait·타입 이름 기반 기본값을 사용합니다.
- 매크로는 `::error_path` 경로를 사용하므로, core crate dependency rename에는 위의 재노출 구성이 필요합니다.

## 관련 문서

- [error-path core crate]https://crates.io/crates/error-path
- [프로젝트 문서와 예제]https://github.com/yongaru/error-path-kit
- [API 문서]https://docs.rs/error-path-macros
- [변경 기록]https://github.com/yongaru/error-path-kit/blob/main/CHANGELOG.md

## 라이선스

Apache-2.0 또는 MIT 라이선스 중 하나를 선택해 사용할 수 있습니다.

## 만든이

용사장이 만들고 관리합니다. [akira76@gmail.com](mailto:akira76@gmail.com)