Aplikasi web melayani permintaan satu per satu dalam jumlah besar — dan setiap permintaan yang butuh data tidak boleh membangun koneksi MongoDB dari nol. Jabatan tangan TCP tiga arah, negosiasi TLS, sampai penemuan topologi replica set semuanya butuh waktu. Driver mongodb menjawabnya dengan connection pool: sekali dibuka, sekumpulan koneksi tinggal dipakai ulang. Pada bagian ini kita menyiapkan fondasi proyek — struktur folder, dependensi, dan modul db.js yang menjadi satu-satunya pintu menuju database.
Struktur Proyek #
Buat folder proyek dan instal satu-satunya dependensi runtime kita:
mkdir api-manajemen-tugas && cd api-manajemen-tugas
npm init -y
npm install mongodb@7Struktur akhir proyek setelah seluruh bagian selesai:
api-manajemen-tugas/
├── src/
│ ├── db.js ← bagian ini: koneksi + pool
│ ├── tugas.js ← Bagian 2: repository tugas
│ ├── validasi.js ← Bagian 3: skema + pemeriksaan payload
│ ├── users.js ← Bagian 4: pengguna + API key
│ └── server.js ← Bagian 2-4: router HTTP
└── tests/
└── api-tes.js ← suite tes mandiriDua aturan arsitektur yang kita pegang: satu modul satu tanggung jawab, dan seluruh akses database lewat modul db.js — tidak ada handler yang membuat MongoClient sendiri, sebagaimana pola yang diperkenalkan chapter Struktur Aplikasi Node.js.
Modul Koneksi #
// db.js — koneksi singleton + connection pool
// Bisa dijalankan langsung untuk menguji koneksi:
// node src/db.js
// Variabel lingkungan (opsional):
// MONGODB_URI connection string (default: server lokal rs0)
// DB_NAME nama database (default: proyek_api_tugas)
const { MongoClient } = require("mongodb");
const URI = process.env.MONGODB_URI ||
"mongodb://127.0.0.1:27017/?directConnection=true";
const NAMA_DB = process.env.DB_NAME || "proyek_api_tugas";
let klien = null;
let db = null;
// Satu pool koneksi untuk seluruh proses — fungsi ini mengembalikan
// handle database yang sama berapa kali pun dipanggil.
async function ambilDb() {
if (db) return db;
klien = new MongoClient(URI, { maxPoolSize: 10 });
await klien.connect();
db = klien.db(NAMA_DB);
return db;
}
// Menutup pool dengan rapi saat proses berhenti.
async function tutupKoneksi() {
if (klien) await klien.close();
klien = null;
db = null;
}
// Cek kesehatan koneksi dengan command ping.
async function ping() {
const d = await ambilDb();
return d.command({ ping: 1 });
}
if (require.main === module) {
ping()
.then(function (hasil) {
console.log("ping ok:", hasil.ok, "| database:", NAMA_DB);
return tutupKoneksi();
})
.catch(function (galat) {
console.error("koneksi gagal:", galat.message);
process.exit(1);
});
}
module.exports = { ambilDb, tutupKoneksi, ping, URI, NAMA_DB };Uji koneksi sebelum menulis hal lain:
node src/db.jsOutput yang Dihasilkan:
ping ok: 1 | database: proyek_api_tugasBedah Modul Baris-per-Baris #
const URI = process.env.MONGODB_URI || ...— connection string dibaca dari variabel lingkungan dengan fallback ke server lokal Course. Praktik ini mengikuti chapter Environment Configuration: kode aplikasi tidak boleh menuliskan alamat server secara tetap agar satu kode yang sama berjalan di laptop dan di server produksi.let db = null+if (db) return db— pola singleton. PanggilanambilDb()pertama membuatMongoClientdan menyambung; panggilan berikutnya menerima handle yang sama tanpa membuka pool baru. Tanpa penjaga ini, setiap handler akan membuka pool masing-masing dan jumlah koneksi ke server tumbuh tanpa kendali.new MongoClient(URI, { maxPoolSize: 10 })— pool dibatasi 10 koneksi simultan, cukup untuk API satu proses. Nilai bawaan driver adalah 100; angka lebih kecil melindungi server bersama ketika beberapa aplikasi menumpuk di satu cluster.ping()— menjalankan commandpingdi database aktif, cara tercepat memastikan seluruh rantai (DNS, TCP, autentikasi, pemilihan node) benar-benar hidup.if (require.main === module)— blok ini hanya berjalan saat berkas dieksekusi langsung (node src/db.js), tidak saat di-requireoleh modul lain. Satu berkas, dua peran: modul dan alat uji.
Konfigurasi Tanpa Kode #
Dua variabel lingkungan cukup untuk mengarahkan ulang seluruh aplikasi. Simpan berkas .env di folder proyek lalu jalankan dengan opsi --env-file bawaan Node.js — tanpa pustaka tambahan:
MONGODB_URI=mongodb://127.0.0.1:27017/?directConnection=true
DB_NAME=proyek_api_tugasnode --env-file=.env src/db.js
DB_NAME=api_uji node src/db.jsOutput yang Dihasilkan:
ping ok: 1 | database: proyek_api_tugas
ping ok: 1 | database: api_ujiPerintah pertama membaca .env; perintah kedua membuktikan variabel biasa menimpa fallback tanpa mengubah satu baris kode. Sebagai pembanding, saat server mati driver mencoba menyambung berulang-ulang selama masa tunggu pemilihan server sebelum menyerah — sesuai siklus hidup koneksi pada chapter Connection Lifecycle:
MONGODB_URI="mongodb://127.0.0.1:27099/" node src/db.jsOutput yang Dihasilkan:
koneksi gagal: connect ECONNREFUSED 127.0.0.1:27099Apa Berikutnya #
Pintu ke database sudah terbuka dan bisa diping kapan pun. Bagian 2 membangun lapisan di atasnya: repository tugas.js yang merangkum seluruh operasi data, lalu server.js yang mengekspos operasi tersebut sebagai endpoint HTTP.