🗼 Tower 통합 가이드

Tower의 Service/Layer 생태계와 Ranvier의 Transition/Outcome/Bus 패러다임을 활용하세요

개요

Tower는 견고한 네트워킹 클라이언트와 서버를 구축하기 위한 모듈식이고 재사용 가능한 컴포넌트 라이브러리입니다. Service 트레이트와 Layer 미들웨어 추상화를 제공하며, 많은 Rust 웹 프레임워크(Axum, Tonic, Hyper 등)의 기반이 됩니다.

Tower와 Ranvier

Ranvier는 "Opinionated Core, Flexible Edges" 원칙을 따릅니다:

  • Core (Opinionated): Transition/Outcome/Bus/Schematic 패러다임은 협상 불가
  • Edges (Flexible): 경계에서 Tower, actix, Axum 또는 모든 Rust 도구 사용 가능

즉, Tower의 ServiceLayer 미들웨어를 Ranvier 트랜지션과 함께 사용하여 두 세계의 장점을 모두 활용할 수 있습니다:

  • Tower: CORS, 추적, 타임아웃, 속도 제한, 인증을 위한 검증된 미들웨어
  • Ranvier: Schematic 시각화, Bus 전파, 조합 가능한 트랜지션

통합 패턴

Tower와 Ranvier를 통합하는 두 가지 주요 패턴이 있습니다:

패턴 1: Tower Layer로 Ranvier 핸들러 래핑

Ranvier 트랜지션 주변에서 HTTP 관심사(CORS, 추적, 타임아웃)에 Tower 레이어 사용:

use tower::ServiceBuilder;
use tower_http::{
    cors::CorsLayer,
    trace::TraceLayer,
    timeout::TimeoutLayer,
};

let service = ServiceBuilder::new()
    .layer(CorsLayer::permissive())
    .layer(TraceLayer::new_for_http())
    .layer(TimeoutLayer::new(Duration::from_secs(30)))
    .service(ranvier_adapter);  // ← Ranvier 핸들러

사용 시기: 검증된 HTTP 미들웨어(CORS, 추적)가 필요한 경우

패턴 2: 인증을 위한 Tower Service

인증에 Tower의 AsyncRequireAuthorizationLayer를 사용한 후 Ranvier로 전달:

use tower_http::auth::{AsyncAuthorizeRequest, AsyncRequireAuthorizationLayer};

#[derive(Clone)]
struct JwtAuthorizer { secret: String }

impl<B> AsyncAuthorizeRequest<B> for JwtAuthorizer {
    type RequestBody = B;
    type ResponseBody = String;
    type Future = Ready<Result<Request<B>, Response<String>>>;

    fn authorize(&mut self, mut request: Request<B>) -> Self::Future {
        // JWT 검증 로직...
        let auth_ctx = validate_jwt(token, &self.secret)?;
        request.extensions_mut().insert(auth_ctx);
        ready(Ok(request))
    }
}

let service = ServiceBuilder::new()
    .layer(AsyncRequireAuthorizationLayer::new(JwtAuthorizer { secret }))
    .service(ranvier_adapter);

사용 시기: 기존 Tower 인증 레이어가 있거나 Tower 기반 서비스와 통합해야 하는 경우

📘 참고

두 패턴 모두 유효합니다. 패턴 1은 HTTP 관심사에 더 간단하고, 패턴 2는 요청/응답 흐름에 대한 완전한 제어를 제공합니다. 자세한 비교는 트레이드오프 섹션을 참조하세요.

인증 예제 안내

Tower + Ranvier 인증의 전체 예제는 examples/auth-tower-integration을 참조하세요.

예제가 보여주는 것

  • 두 가지 접근법: 수동 Layer + Service 구현(교육용)과 고수준 AsyncAuthorizeRequest 트레이트(권장)
  • JWT 검증: Tower 레이어가 JWT를 검증하고 AuthContext를 요청 확장에 저장
  • Ranvier 트랜지션: 비즈니스 로직이 Bus에서 AuthContext를 읽음(어댑터가 확장에서 추출)

핵심 통찰

Tower가 토큰 검증 → AuthContextrequest.extensions()에 저장 → 어댑터가 Bus로 추출 → Ranvier 트랜지션이 Bus에서 접근.

예제 실행

cd examples/auth-tower-integration
cargo run

# 출력:
# INFO Tower auth layer configured (JWT validation)
# INFO Ranvier pipeline configured (business logic)
# ✅ Success: {"message":"Hello, alice! (Verified by Tower)",...}

Tower 통합 사용 시기

✅ 좋은 사용 사례

  • 기존 Tower 앱이 있고 Ranvier를 점진적으로 추가하려는 경우
  • 팀이 이미 Tower를 알고 있고 그 지식을 활용하고 싶은 경우
  • 특정 Tower 미들웨어(CORS, 속도 제한, 압축)가 필요한 경우
  • Tower를 사용하는 다른 프레임워크에서 마이그레이션(Axum, Tonic)하는 경우
  • Ranvier에서 재구현하지 않고 검증된 미들웨어를 원하는 경우

❌ 권장하지 않는 경우

  • 새 프로젝트를 시작하고 완전한 Schematic 시각화를 원하는 경우 (대신 순수 Ranvier 사용)
  • Bus를 통한 타입 안전 컨텍스트 전파를 우선시하는 경우 (Tower는 요청 확장 사용)
  • 트랜지션을 독립적으로 테스트하려는 경우 (Tower 통합은 HTTP 모의 객체 필요)

💡 권장사항

새 프로젝트의 경우 Transition 기반 인증 (examples/auth-transition)을 선호하세요. 더 나은 Schematic 시각화, Bus 전파, 테스트 가능성을 제공합니다.

기존 Tower 앱에서 점진적 마이그레이션하거나 Ranvier가 제공하지 않는 특정 Tower 미들웨어가 필요한 경우 Tower 통합을 사용하세요.

트레이드오프

Tower 통합에는 장점과 한계가 모두 있습니다:

측면Tower 통합순수 Ranvier (Transition 기반)
생태계 호환성✅ Tower 레이어 전체 접근❌ Ranvier 전용
Schematic 시각화❌ Tower 레이어는 불투명✅ Circuit 뷰에서 완전한 가시성
컨텍스트 전파⚠️ 요청 확장 (런타임)✅ Bus (컴파일 타임 타입 안전)
테스팅⚠️ 통합 테스트 필요✅ 쉬운 단위 테스트 (Bus 주입)
팀 온보딩✅ Tower 지식 활용⚠️ Ranvier 패러다임 학습
보일러플레이트❌ 50-150 줄 (Service 트레이트)✅ 20 줄 (transition 매크로)
성능✅ 동일 (제로 코스트)✅ 동일 (제로 코스트)

범례: ✅ 강력한 장점 | ⚠️ 주의사항과 함께 사용 가능 | ❌ 중요한 제한사항