Router 시작하기
Last update - 2025. 9. 5.
개요
Router는 Orbital에서 LUNE 프로토콜 메시지를 적절한 핸들러로 라우팅하는 역할을 담당합니다. Express.js와 유사한 API를 제공하며, RESTful 설계 패턴, 미들웨어 체인, 경로 매개변수 등을 지원합니다.
기본 사용법
Router 생성
use orbital::router::Router;
// 기본 라우터 생성
let router = Router::new("My Router");
// 베이스 경로와 함께 생성
let api_router = Router::with_base_path("API Router", "/api");
기본 라우트 등록
use orbital::router::{Router, RouteResponse, RouteContext};
use serde_json::json;
use std::sync::Arc;
let mut router = Router::new("Main Router");
// READ 라우트 (GET과 유사)
router.read("/", Arc::new(|_ctx: RouteContext| {
Ok(RouteResponse::json(json!({
"message": "Welcome to Orbital!",
"protocol": "LUNE/1"
})))
}));
router.read("/about", Arc::new(|_ctx: RouteContext| {
Ok(RouteResponse::text("About page"))
}));
// CREATE 라우트 (POST와 유사)
router.create("/users", Arc::new(|ctx: RouteContext| {
let name = ctx.body_field("name")
.and_then(|v| v.as_str())
.unwrap_or("Unknown");
Ok(RouteResponse::created(json!({
"id": 123,
"name": name,
"created_at": chrono::Utc::now().to_rfc3339()
})))
}));
LUNE 프로토콜 메서드
Router는 LUNE 프로토콜의 CRUD 메서드들을 지원합니다:
use orbital::router::{Router, RouteResponse};
use std::sync::Arc;
let mut router = Router::new("CRUD Router");
// READ - 데이터 조회 (HTTP GET과 유사)
router.read("/users", Arc::new(|_ctx| {
Ok(RouteResponse::json(serde_json::json!({
"users": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
]
})))
}));
// CREATE - 데이터 생성 (HTTP POST와 유사)
router.create("/users", Arc::new(|ctx| {
let name = ctx.body_field("name")
.and_then(|v| v.as_str())
.unwrap_or("Unknown");
Ok(RouteResponse::created(serde_json::json!({
"id": 123,
"name": name
})))
}));
// UPDATE - 데이터 수정 (HTTP PUT과 유사)
router.update("/users/:id", Arc::new(|ctx| {
let user_id = ctx.param("id").unwrap_or("0".to_string());
let name = ctx.body_field("name")
.and_then(|v| v.as_str())
.unwrap_or("Unknown");
Ok(RouteResponse::json(serde_json::json!({
"id": user_id.parse::<i32>().unwrap_or(0),
"name": name,
"updated_at": chrono::Utc::now().to_rfc3339()
})))
}));
// REMOVE - 데이터 삭제 (HTTP DELETE와 유사)
router.remove("/users/:id", Arc::new(|ctx| {
let user_id = ctx.param("id").unwrap_or("0".to_string());
Ok(RouteResponse::json(serde_json::json!({
"message": format!("User {} deleted", user_id),
"deleted_at": chrono::Utc::now().to_rfc3339()
})))
}));
JSON 응답을 위한 편의 메서드
// read_json - JSON 응답을 직접 반환
router.read_json("/simple", |_ctx| {
serde_json::json!({
"message": "Simple JSON response",
"timestamp": chrono::Utc::now().timestamp()
})
});
// 다른 메서드들도 _json 변형이 있습니다
router.create_json("/simple-create", |ctx| {
serde_json::json!({
"created": true,
"data": ctx.body_json().unwrap_or_default()
})
});
경로 매개변수
단일 매개변수
async fn get_user(ctx: RouteContext) -> Result<RouteResponse, Box<dyn std::error::Error>> {
let user_id = ctx.param("id").unwrap_or("0".to_string());
Ok(RouteResponse::json(serde_json::json!({
"user_id": user_id,
"name": "John Doe"
})))
}
router.read("/users/:id", Arc::new(get_user));
여러 매개변수
router.read("/users/:user_id/posts/:post_id", Arc::new(|ctx| {
let user_id = ctx.param("user_id").unwrap_or("0".to_string());
let post_id = ctx.param("post_id").unwrap_or("0".to_string());
Ok(RouteResponse::json(serde_json::json!({
"user_id": user_id,
"post_id": post_id,
"title": "Sample Post"
})))
}));
와일드카드 매개변수
router.read("/files/*", Arc::new(|ctx| {
let path = ctx.param("*").unwrap_or("".to_string());
Ok(RouteResponse::text(format!("Caught path: {}", path)))
}));
요청 및 응답 처리
요청 데이터 접근
router.create("/users", Arc::new(|ctx| {
// JSON 본문 전체 파싱
let body_json = ctx.body_json()?;
// 특정 필드 접근
let name = ctx.body_field("name")
.and_then(|v| v.as_str())
.unwrap_or("Unknown");
let email = ctx.body_field("email")
.and_then(|v| v.as_str())
.unwrap_or("");
// LUNE 메시지 접근
let lune_message = ctx.lune_message();
let message_type = lune_message.header().message_type();
// 연결 ID
let connection_id = ctx.connection_id();
Ok(RouteResponse::created(serde_json::json!({
"user": {
"name": name,
"email": email
},
"meta": {
"message_type": message_type,
"connection_id": connection_id
}
})))
}));
다양한 응답 타입
// JSON 응답
let json_response = RouteResponse::json(serde_json::json!({
"message": "Success",
"data": {"id": 123}
}));
// 텍스트 응답
let text_response = RouteResponse::text("Hello, World!");
// 에러 응답
let error_response = RouteResponse::error(404, "Not Found");
// 생성 응답 (201 Created)
let created_response = RouteResponse::created(serde_json::json!({
"id": 456,
"created_at": chrono::Utc::now().to_rfc3339()
}));
// 커스텀 응답
let custom_response = RouteResponse::new()
.status(201)
.header("Content-Type", "application/json")
.header("X-Custom-Header", "custom-value")
.body(b"Custom response body".to_vec());
라우트 그룹화
베이스 경로를 사용한 그룹화
use orbital::application::OrbitApplication;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut app = OrbitApplication::new(None, None, None);
// API v1 라우터
let mut api_v1_router = Router::with_base_path("API v1", "/api/v1");
api_v1_router.read("/users", Arc::new(|_ctx| {
Ok(RouteResponse::json(serde_json::json!({"version": "1.0"})))
}));
// API v2 라우터
let mut api_v2_router = Router::with_base_path("API v2", "/api/v2");
api_v2_router.read("/users", Arc::new(|_ctx| {
Ok(RouteResponse::json(serde_json::json!({"version": "2.0"})))
}));
// 관리자 라우터
let mut admin_router = Router::with_base_path("Admin", "/admin");
admin_router.read("/dashboard", Arc::new(|_ctx| {
Ok(RouteResponse::json(serde_json::json!({"page": "dashboard"})))
}));
app.register_routers(vec![api_v1_router, api_v2_router, admin_router])?;
app.listen(8080).await?;
Ok(())
}
빠른 시작 예제
RESTful API 서버
use orbital::application::OrbitApplication;
use orbital::router::{Router, RouteResponse};
use serde_json::json;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut app = OrbitApplication::new(
Some("RESTful Server".to_string()),
None,
None
);
let mut users_router = Router::with_base_path("Users API", "/api/users");
// 사용자 목록
users_router.read("/", Arc::new(|_ctx| {
Ok(RouteResponse::json(json!({
"users": [
{"id": 1, "name": "Alice", "email": "alice@example.com"},
{"id": 2, "name": "Bob", "email": "bob@example.com"},
{"id": 3, "name": "Charlie", "email": "charlie@example.com"}
]
})))
}));
// 특정 사용자
users_router.read("/:id", Arc::new(|ctx| {
let user_id = ctx.param("id").unwrap_or("0".to_string());
Ok(RouteResponse::json(json!({
"user": {
"id": user_id.parse::<i32>().unwrap_or(0),
"name": format!("User {}", user_id),
"email": format!("user{}@example.com", user_id)
}
})))
}));
// 사용자 생성
users_router.create("/", Arc::new(|ctx| {
let name = ctx.body_field("name")
.and_then(|v| v.as_str())
.unwrap_or("Unknown");
let email = ctx.body_field("email")
.and_then(|v| v.as_str())
.unwrap_or("");
Ok(RouteResponse::created(json!({
"user": {
"id": 999,
"name": name,
"email": email,
"created_at": chrono::Utc::now().to_rfc3339()
}
})))
}));
// 사용자 수정
users_router.update("/:id", Arc::new(|ctx| {
let user_id = ctx.param("id").unwrap_or("0".to_string());
let name = ctx.body_field("name")
.and_then(|v| v.as_str())
.unwrap_or("Unknown");
Ok(RouteResponse::json(json!({
"user": {
"id": user_id.parse::<i32>().unwrap_or(0),
"name": name,
"updated_at": chrono::Utc::now().to_rfc3339()
}
})))
}));
// 사용자 삭제
users_router.remove("/:id", Arc::new(|ctx| {
let user_id = ctx.param("id").unwrap_or("0".to_string());
Ok(RouteResponse::json(json!({
"message": format!("User {} deleted successfully", user_id),
"deleted_at": chrono::Utc::now().to_rfc3339()
})))
}));
app.register(users_router)?;
println!("🚀 RESTful API 서버가 포트 8080에서 시작됩니다...");
println!("📡 사용 가능한 엔드포인트:");
println!(" READ /api/users - 사용자 목록");
println!(" READ /api/users/:id - 특정 사용자");
println!(" CREATE /api/users - 사용자 생성");
println!(" UPDATE /api/users/:id - 사용자 수정");
println!(" REMOVE /api/users/:id - 사용자 삭제");
app.listen(8080).await?;
Ok(())
}
다음 단계
Router의 기본 사용법을 익혔다면, 다음 문서들을 통해 더 고급 기능들을 살펴보세요: