Belajar Axum - Setup Project & Struktur Awal
Episode 3 of 28

Belajar Axum - Setup Project & Struktur Awal

Membuat project Cargo dari nol, menambahkan dependencies Axum + tokio + tower-http, menulis hello world server pertama, dan memahami struktur folder yang rapi agar project siap tumbuh sampai 25 episode ke depan.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Di episode 2 kita sudah memahami arsitektur: request mengalir dari tokio → hyper → tower → Router → handler. Sekarang saatnya tangan di keyboard. Episode ini adalah fondasi praktis pertama: kalian akan membuat project Cargo, menambahkan dependencies yang tepat, menulis hello world server Axum, dan menata struktur folder agar project tidak menjadi bola kusut saat kita menambahkan CRUD, WebSocket, dan auth di episode-episode berikutnya.

Mengapa struktur folder penting sedini mungkin? Karena Axum menggemakan prinsip library-oriented — komponen hidup terpisah. Project yang menata modul dengan jelas akan jauh lebih mudah di-refactor, diuji, dan dipahami orang lain. Kita akan memilih struktur yang seimbang: tidak over-engineer untuk "hello world", tetapi cukup untuk menampung semua yang akan datang.

Membuat Project Cargo

Mulai dengan project baru. Nama binary kita pakai axum-api:

Buat project Cargo
cargo new axum-api
cd axum-api

Periksa isi default yang dibuat cargo:

Struktur awal
tree -a
Output
.
├── .git
├── .gitignore
├── Cargo.toml
└── src
    └── main.rs

Menambahkan Dependencies

Dependencies inti untuk memulai server:

Tambah dependencies
cargo add axum@0.8
cargo add tokio@1 --features rt-multi-thread,macros,signal
cargo add tower-http --features trace
cargo add serde --features derive
cargo add serde_json
cargo add tracing
cargo add tracing-subscriber --features env-filter

cargo add memilih versi terbaru yang kompatibel dan menulis ke Cargo.toml secara otomatis. Cek hasilnya:

Cargo.toml
[package]
name = "axum-api"
version = "0.1.0"
edition = "2021"
 
[dependencies]
axum = "0.8"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["rt-multi-thread", "macros", "signal"] }
tower-http = { version = "0.6", features = ["trace"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

Catatan penting soal fitur tokio:

  • rt-multi-thread — runtime tokio multi-thread (bukan current-thread).
  • macros — untuk #[tokio::main].
  • signal — untuk menangkap sinyal shutdown di episode 16.

Tanpa fitur yang tepat, kode tidak akan compile meskipun crate terpasang — fitur tokio bersifat opt-in secara sengaja untuk menjaga ukuran binary.

Hello World Pertama

Tulis server pertama di src/main.rs:

src/main.rs
use axum::{routing::get, Router};
use tokio::net::TcpListener;
 
#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(|| async { "Hello, Axum!" }));
 
    let listener = TcpListener::bind("127.0.0.1:3000").await.unwrap();
    println!("listening on {}", listener.local_addr().unwrap());
    axum::serve(listener, app).await.unwrap();
}

Mari bedah baris per baris:

  • #[tokio::main] — macro yang membungkus main untuk menjalankan async runtime tokio multi-thread.
  • Router::new() — router kosong; setiap route ditambahkan via .route(...).
  • get(|| async { "Hello, Axum!" }) — handler GET yang berupa closure. String literal &'static str otomatis IntoResponse, jadi langsung menjadi body respons.
  • axum::serve(listener, app) — fungsi utama Axum 0.8 untuk menjalankan server; menerima TcpListener (tokio) dan router. Versi lama memakai tokio::net::TcpListener dengan axum::Server dari hyper — sejak 0.7, axum::serve adalah cara modern.

Jalankan server:

Jalankan server
cargo run

Uji di terminal lain:

Uji dengan curl
curl http://127.0.0.1:3000/
Output
Hello, Axum!

Tip

Gunakan cargo watch -x run agar server otomatis restart setiap file berubah — menghemat waktu saat eksperimen. Install dengan cargo install cargo-watch.

Menambah Logging Dasar

Response "listening on ..." sebaiknya diganti dengan logging terstruktur — kita akan memakai tracing secara penuh di episode 17, tapi memulai lebih awal tidak ada salahnya:

src/main.rs dengan tracing
use axum::{routing::get, Router};
use tokio::net::TcpListener;
use tracing::info;
 
#[tokio::main]
async fn main() {
    tracing_subscriber::fmt()
        .with_env_filter("axum_api=debug,tower_http=debug")
        .init();
 
    let app = Router::new().route("/", get(|| async { "Hello, Axum!" }));
 
    let listener = TcpListener::bind("127.0.0.1:3000").await.unwrap();
    info!("server berjalan di {}", listener.local_addr().unwrap());
    axum::serve(listener, app).await.unwrap();
}

with_env_filter memungkinkan kita mengontrol level log lewat env var RUST_LOG saat runtime — pola yang akan kita formalisasi di episode 16 dan 17.

Struktur Folder untuk Project yang Tumbuh

Untuk episode ini, satu file main.rs sudah cukup. Tapi mari kita siapkan struktur yang akan dipakai sepanjang series — dipecah menjadi modul per domain:

Struktur modul
src
├── main.rs
├── routes
   ├── mod.rs
   ├── health.rs
   └── hello.rs
├── handlers
   ├── mod.rs
   └── hello.rs
├── models
   └── mod.rs
├── state.rs
└── error.rs

Penjelasan per folder:

FolderIsiDibahas Di
routesDefinisi Router per domainEpisode 4
handlersImplementasi handlerEpisode 4-6
modelsStruktur data & skema serdeEpisode 5, 9
state.rsApp state (DB pool, config)Episode 7
error.rsTipe error & IntoResponseEpisode 6

Tapi jangan menyalin struktur ini ke project hello world kalian sekarang. Prinsip yang sehat: pecah modul saat file sudah terasa padat atau saat kalian butuh menambah domain baru. Untuk episode 3-8, satu main.rs tetap paling praktis — kita baru benar-benar membagi modul saat project masuk fase CRUD di episode 9.

Note

Aturan praktis arsitektur Rust: jangan buat folder abstrak kosong. Mulailah dari satu file, dan pecah ketika ada dua modul yang benar-benar saling bebas (misalnya routes vs models). Struktur di atas adalah tujuan akhir, bukan titik awal.

Verifikasi Proyek

Sebelum lanjut, pastikan tiga hal beres:

Verifikasi project
cargo check          # cepat, pastikan tidak ada error tipe
cargo run            # pastikan server bisa start
curl http://127.0.0.1:3000/  # pastikan respons benar

cargo check jauh lebih cepat daripada cargo build dan sebaiknya jadi refleks setiap selesai mengubah kode — kita akan memakainya terus sepanjang series.

Penutup

Pada episode 3 ini kalian sudah menulis server Axum pertama:

  • Project Cargo dibuat dengan cargo new, dependencies ditambah via cargo add.
  • Fitur tokio wajib: rt-multi-thread, macros, signal.
  • Server dijalankan dengan axum::serve di atas TcpListener tokio.
  • Logging tracing mulai terpasang sejak dini.
  • Struktur modul dipahami sebagai tujuan, bukan dipaksakan di awal.

Di episode 4 selanjutnya kita akan memperluas routing: nested routes, path params, query params, wildcard, fallback, dan merge — dasar yang wajib dikuasai sebelum membangun REST API sungguhan. Pastikan server hello world kalian berjalan, karena episode 4 akan mengubahnya menjadi router multi-route!

Belajar Axum - Setup Project & Struktur Awal | Belajar Axum