저는 이제 러스트를 배우기 시작했어요

발행: (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,
}
Back to Blog

관련 글

더 보기 »

RwLock HashMap Arc Mutex 파일

rust pub struct Context { pubcrate tools: HashMap>, pubcrate fifos: tokio::sync::RwLock>>>, // ^ ^ ^ } // 많은 FIFO가 있지만, async ref 카운터만 사용됩니다.

Markdown Scribe 구축

저는 오래전부터 Rust를 시도하고 싶어했던 개발자입니다. 이번 겨울 방학에 드디어 뛰어들었어요—더 이상 변명은 없습니다. 독학자로서 저는 방대한 튜토리얼을 건너뛰고 집중했습니다...