저는 이제 러스트를 배우기 시작했어요
발행: (2026년 1월 4일 오후 02:18 GMT+9)
3 min read
원문: Dev.to
Source: Dev.to
임포트
use axum::{
Json, Router,
extract::State,
http::StatusCode,
routing::{get, post},
};
use rusqlite::Connection;
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};
use tokio::task;
// Ref: how to use app state
// https://users.rust-lang.org/t/how-to-pass-app-state-in-axum/104458/3
로컬 모듈
// define local module. the file at app_infra/mod.rs
mod app_infra;
애플리케이션 상태
#[derive(Debug, Clone)]
struct AppState {
// Ref: how to make un‑clonable object in external mod implementing Clone traits
// https://itsallaboutthebit.com/arc-mutex/
// Arc: shared ownership across threads
// Mutex: exclusive access to the inner value
db: Arc>,
}
main 함수
#[tokio::main]
async fn main() {
// initialize tracing
tracing_subscriber::fmt::init();
// create a SQLite connection (implementation in `app_infra`)
let db = match app_infra::create_db_connection() {
Ok(conn) => conn,
Err(err) => panic!("error to connect to db {}", err),
};
let cloneable_db = Arc::new(Mutex::new(db));
let app_state = AppState { db: cloneable_db };
// build the router
let app = Router::new()
.route("/", get(root)) // GET /
.route("/users", post(create_user)) // POST /users
.with_state(app_state);
// run the server on port 3000
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
}
핸들러
루트 핸들러
// Basic handler that responds with a static string
async fn root(State(AppState { db }): State) -> &'static str {
let outside_int = 213_123i32;
// Use `spawn_blocking` because SQLite I/O is blocking
// Ref: https://stackoverflow.com/a/75840352
// Ref: spawn vs spawn_blocking https://stackoverflow.com/a/74547875
let res = task::spawn_blocking(move || -> Result, rusqlite::Error> {
let mut all_item: Vec = Vec::new();
// Acquire the mutex lock
let locked_db = db.lock().unwrap();
// Simple query example
let mut stmt = locked_db.prepare("SELECT * FROM memo LIMIT 1")?;
let mut rows = stmt.query([])?;
match rows.next() {
Ok(Some(row)) => println!("{:?}", row),
Ok(None) => (),
Err(_) => (),
};
println!("testing outsider variable {:?}", outside_int);
all_item.push("Mantab".to_string());
// Mutex is released when `locked_db` goes out of scope
Ok(all_item)
})
.await
.unwrap();
// Handle the result (ignore the value for this example)
let _ = match res {
Ok(it) => {
println!("testing modify variable {:?}", it);
it
}
Err(_) => Vec::::new(),
};
"Hello, World!"
}
사용자 생성 핸들러
async fn create_user(
// Parse the request body as JSON into `CreateUser`
Json(payload): Json,
) -> (StatusCode, Json) {
// Application logic (placeholder)
let user = User {
id: 1337,
username: payload.username,
};
// Return `201 Created` with the user as JSON
(StatusCode::CREATED, Json(user))
}
데이터 구조
// Input for `create_user`
#[derive(Deserialize)]
struct CreateUser {
username: String,
}
// Output for `create_user`
#[derive(Serialize)]
struct User {
id: u64,
username: String,
}