#Axum 통합 가이드
버전: 0.33.0 최종 업데이트: 2026-03-15 적용 대상: ranvier-core, ranvier-macros, ranvier-runtime 카테고리: 통합
Axum의 인체공학적 API와 Ranvier의 Schematic 워크플로우를 결합하세요.
#개요
Axum은 Tower 위에 구축된 인체공학과 모듈성에 초점을 맞춘 웹 프레임워크입니다. Ranvier transition을 Axum 핸들러와 통합하여 다음을 결합할 수 있습니다:
- Axum: 타입 안전 extractor, 상태 관리, Tower 미들웨어
- Ranvier: Schematic 시각화, Bus 전파, 조합 가능한 로직
#통합 패턴
권장 접근 방식은 Axum 핸들러에서 Ranvier transition을 호출하는 것입니다:
#Axum 핸들러에서 Ranvier Transition 호출
use axum::{
extract::{State, Json},
http::StatusCode,
response::IntoResponse,
Router,
};
use ranvier_core::{Bus, Outcome};
use ranvier_macros::transition;
use ranvier_runtime::Axon;
use std::sync::Arc;
// 공유 앱 상태
#[derive(Clone)]
struct AppState {
pipeline: Axon<CreateUser, User, AppError, ()>,
}
// Ranvier transition
#[transition]
async fn create_user(
input: CreateUser,
_res: &(),
bus: &mut Bus
) -> Outcome<User, AppError> {
// 비즈니스 로직
Outcome::Next(User { id: 1, name: input.name })
}
// Axum 핸들러
async fn create_user_handler(
State(state): State<Arc<AppState>>,
Json(payload): Json<CreateUser>
) -> impl IntoResponse {
let mut bus = Bus::new();
match state.pipeline.execute(payload, &(), &mut bus).await {
Outcome::Next(user) => (StatusCode::CREATED, Json(user)).into_response(),
Outcome::Fault(err) => (StatusCode::BAD_REQUEST, Json(err)).into_response(),
_ => StatusCode::INTERNAL_SERVER_ERROR.into_response(),
}
}
// Axum 앱
#[tokio::main]
async fn main() {
let pipeline = Axon::simple::<AppError>("create-user")
.then(create_user);
let state = Arc::new(AppState { pipeline });
let app = Router::new()
.route("/users", axum::routing::post(create_user_handler))
.with_state(state);
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}#Ranvier와 함께 Axum Extractor 사용
use axum::{
extract::{Extension, TypedHeader},
headers::Authorization,
headers::authorization::Bearer,
};
async fn protected_handler(
TypedHeader(auth): TypedHeader<Authorization<Bearer>>, // Axum extractor
State(state): State<Arc<AppState>>,
Json(data): Json<RequestData>
) -> impl IntoResponse {
let mut bus = Bus::new();
// 추출된 토큰을 Ranvier transition을 위해 Bus에 저장
bus.insert(auth.token().to_string());
match state.pipeline.execute(data, &(), &mut bus).await {
Outcome::Next(result) => (StatusCode::OK, Json(result)).into_response(),
Outcome::Fault(err) => (StatusCode::UNAUTHORIZED, Json(err)).into_response(),
_ => StatusCode::INTERNAL_SERVER_ERROR.into_response(),
}
}#Axum과 Ranvier 간 상태 공유
// Axum 상태에 앱 설정과 Ranvier 파이프라인 모두 포함
#[derive(Clone)]
struct AppState {
db: Arc<DatabasePool>,
order_pipeline: Axon<Order, OrderResult, AppError, ()>,
user_pipeline: Axon<CreateUser, User, AppError, ()>,
}
// 핸들러에서 Axum 상태 접근과 Ranvier 파이프라인 실행 모두 수행
async fn process_order(
State(state): State<Arc<AppState>>,
Json(order): Json<Order>
) -> impl IntoResponse {
let mut bus = Bus::new();
// Axum이 관리하는 리소스를 Ranvier transition을 위해 Bus에 저장
bus.insert(state.db.clone());
state.order_pipeline.execute(order, &(), &mut bus).await
// ... 결과 처리
}#이 접근 방식을 사용해야 할 때
적합한 경우:
- 기존 Axum 앱에 복잡한 워크플로우를 위해 Ranvier를 추가하는 경우
- Axum의 타입 안전 extractor에 익숙한 팀
- Ranvier 비즈니스 로직과 함께 Tower 미들웨어를 원하는 경우
- 다단계 프로세스에 Ranvier의 Schematic 시각화가 필요한 경우
고려사항:
- 상태 연결: Axum
State를 Ranvier Bus로 수동으로 연결해야 함 - 미들웨어 가시성: Axum 미들웨어(Tower 레이어)는 Ranvier Schematic에 표시되지 않음
- 테스트: Axum 핸들러에 대한 통합 테스트, Ranvier transition에 대한 단위 테스트
#트레이드오프
| 측면 | 장점 | 제한사항 |
|---|---|---|
| Extractor | Axum의 타입 안전 extractor (Json, State, TypedHeader) | Bus로의 수동 연결 필요 |
| Tower 미들웨어 | Axum 레이어를 통한 전체 Tower 생태계 | Ranvier Schematic에서 보이지 않음 |
| 상태 관리 | Axum의 인체공학적 State 공유 | State + Bus 이중 관리 |
| 비즈니스 로직 | Schematic 시각화가 포함된 Ranvier transition | Axum-Ranvier 통합을 위한 추가 보일러플레이트 |
#대안과의 비교
- 순수 Ranvier 대비: Axum 통합은 타입 안전 extractor와 Tower 미들웨어를 제공하지만 일부 Schematic 가시성을 잃음
- Tower 통합 대비: Axum은 Tower 위에 더 높은 수준의 인체공학을 제공 (extractor, 라우팅)
- actix 통합 대비: Axum은 타입 기반 extractor를, actix는 트레이트 기반 extractor를 사용
#관련 문서
- Tower 통합 — Axum은 Tower 위에 구축됨
- actix-web 통합 — 대안 프레임워크 통합