Cara Membangun Aplikasi CRUD dengan Node.js

Node.js adalah lingkungan runtime JavaScript yang berjalan di sisi server dan sering dimanfaatkan untuk membangun berbagai jenis aplikasi web, termasuk aplikasi CRUD (Create, Read, Update, Delete). CRUD adalah istilah yang menggambarkan empat operasi dasar pada data: penambahan, pembacaan, pembaruan, dan penghapusan. Dalam artikel ini, kita akan membahas cara membangun aplikasi CRUD menggunakan Node.js, lengkap dengan Express sebagai framework HTTP dan contoh penggunaan database.


1. Persiapan Dasar

1.1. Instalasi Node.js

Sebelum memulai, pastikan Node.js telah terpasang di komputer. Untuk memverifikasi, buka terminal dan ketik:

node -v

Jika Node.js belum terpasang, silakan unduh installer dari Node.js dan ikuti petunjuk pemasangannya.

1.2. Membuat Folder Proyek

Setelah Node.js siap, buat direktori proyek baru:

mkdir crud-app
cd crud-app

Kemudian inisialisasi package.json:

npm init -y

File package.json akan dihasilkan secara otomatis dengan konfigurasi default.

1.3. Instalasi Dependensi

Kita akan menggunakan beberapa dependensi dasar:

  1. Express: Untuk mempermudah pembuatan server HTTP dan manajemen routing.
  2. cors (opsional): Untuk menangani kebijakan Cross-Origin Resource Sharing jika ingin diakses dari domain berbeda.
  3. body-parser (atau fitur bawaan Express) untuk memproses request body.
  4. dotenv: Agar dapat menyimpan variabel sensitif (seperti kredensial database) di file .env.
  5. Driver database (misalnya mysql2 untuk MySQL atau mongoose untuk MongoDB) tergantung pilihanmu.

Sebagai contoh, kita akan menggunakan MySQL. Install semuanya:

npm install express cors mysql2 dotenv

Apabila lebih menyukai MongoDB, silakan ganti mysql2 dengan mongoose, lalu menyesuaikan script.


2. Struktur Proyek

Untuk kemudahan pengembangan, kita akan menata struktur direktori secara modular. Berikut contoh strukturnya:

crud-app/
├─ config/
│   └─ db.js
├─ controllers/
│   └─ userController.js
├─ models/
│   └─ userModel.js     (opsional, jika ingin pakai ORM/structured approach)
├─ routes/
│   └─ userRoutes.js
├─ .env
├─ app.js
├─ package.json
└─ package-lock.json

Penjelasan singkat:


3. Koneksi Database (MySQL)

3.1. Menyiapkan Database

Pertama-tama, pastikan MySQL sudah terpasang. Buka MySQL CLI atau MySQL Workbench, lalu buat database baru:

CREATE DATABASE crud_db;
USE crud_db;

Buat tabel sederhana, misalnya untuk menyimpan data pengguna:

CREATE TABLE users (
  id INT AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  email VARCHAR(50) NOT NULL,
  age INT
);

Struktur di atas akan menampung data dengan kolom name, email, dan age.

3.2. File Konfigurasi .env

Untuk menyimpan kredensial database, kita buat file .env di root folder:

DB_HOST=localhost
DB_USER=root
DB_PASS=your_password
DB_NAME=crud_db
DB_PORT=3306

Pastikan file .env dimasukkan ke .gitignore agar tidak tersimpan ke repositori publik.

3.3. Membuat db.js di Folder config

Buatlah file config/db.js untuk mengelola koneksi MySQL:

require('dotenv').config();
const mysql = require('mysql2');

// Membuat pool koneksi
const pool = mysql.createPool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: process.env.DB_NAME,
  port: process.env.DB_PORT,
  connectionLimit: 10
});

module.exports = pool;

Dengan mengekspor pool, kita bisa melakukan query di bagian lain aplikasi menggunakan pool tersebut.


4. Membuat Struktur Dasar Aplikasi di app.js

Kita akan membuat file utama bernama app.js:

require('dotenv').config();
const express = require('express');
const cors = require('cors');

const app = express();

// Middleware
app.use(cors());
app.use(express.json());

// Routes
const userRoutes = require('./routes/userRoutes');
app.use('/api/users', userRoutes);

// Jalankan server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server berjalan di port ${PORT}`);
});

Penjelasan ringkas:

  1. Memuat Variabel Lingkungan: require('dotenv').config();
  2. Mengimpor Express dan cors: Agar kita dapat mengelola request/response dengan mudah dan mengizinkan cross-origin jika dibutuhkan.
  3. express.json(): Otomatis mem-parsing request body JSON yang dikirim klien.
  4. Routing: Kita memisahkan rute terkait users ke dalam userRoutes, sehingga lebih terstruktur.
  5. Menjalankan Server: Kita menentukan port, defaultnya 3000 jika .env tidak menyediakan.

5. Routing dan Controller

5.1. File userRoutes.js

Buat file routes/userRoutes.js untuk mendefinisikan URL endpoints terkait user:

const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');

// CREATE
router.post('/', userController.createUser);

// READ
router.get('/', userController.getAllUsers);
router.get('/:id', userController.getUserById);

// UPDATE
router.put('/:id', userController.updateUser);

// DELETE
router.delete('/:id', userController.deleteUser);

module.exports = router;

Di sini, kita mendefinisikan empat method HTTP untuk operasi CRUD:

Setiap endpoint akan memanggil fungsi dari userController.

5.2. File userController.js

Sekarang buat file controllers/userController.js untuk menampung logika masing-masing endpoint:

const pool = require('../config/db');

// CREATE
exports.createUser = (req, res) => {
  const { name, email, age } = req.body;
  const sql = 'INSERT INTO users (name, email, age) VALUES (?, ?, ?)';
  
  pool.query(sql, [name, email, age], (err, result) => {
    if (err) {
      return res.status(500).json({ error: err.message });
    }
    // result.insertId berisi ID user yang baru ditambahkan
    res.status(201).json({ message: 'User ditambahkan', userId: result.insertId });
  });
};

// READ - GET ALL USERS
exports.getAllUsers = (req, res) => {
  const sql = 'SELECT * FROM users';
  pool.query(sql, (err, rows) => {
    if (err) {
      return res.status(500).json({ error: err.message });
    }
    res.json(rows);
  });
};

// READ - GET USER BY ID
exports.getUserById = (req, res) => {
  const userId = req.params.id;
  const sql = 'SELECT * FROM users WHERE id = ?';
  
  pool.query(sql, [userId], (err, rows) => {
    if (err) {
      return res.status(500).json({ error: err.message });
    }
    if (rows.length === 0) {
      return res.status(404).json({ message: 'User tidak ditemukan' });
    }
    res.json(rows[0]);
  });
};

// UPDATE
exports.updateUser = (req, res) => {
  const userId = req.params.id;
  const { name, email, age } = req.body;
  const sql = 'UPDATE users SET name = ?, email = ?, age = ? WHERE id = ?';

  pool.query(sql, [name, email, age, userId], (err, result) => {
    if (err) {
      return res.status(500).json({ error: err.message });
    }
    if (result.affectedRows === 0) {
      return res.status(404).json({ message: 'User tidak ditemukan' });
    }
    res.json({ message: 'User diperbarui' });
  });
};

// DELETE
exports.deleteUser = (req, res) => {
  const userId = req.params.id;
  const sql = 'DELETE FROM users WHERE id = ?';

  pool.query(sql, [userId], (err, result) => {
    if (err) {
      return res.status(500).json({ error: err.message });
    }
    if (result.affectedRows === 0) {
      return res.status(404).json({ message: 'User tidak ditemukan' });
    }
    res.json({ message: 'User dihapus' });
  });
};

Penjelasan Singkat:

  1. createUser: Menambahkan data pengguna baru. Jika sukses, balas dengan kode HTTP 201 (Created) dan kembalikan ID data yang baru tersimpan.
  2. getAllUsers: Mengambil semua data users dari tabel. Kembalikan hasil query berbentuk array JSON.
  3. getUserById: Mengambil data user berdasarkan id yang diambil dari parameter URL.
  4. updateUser: Memperbarui data user berdasarkan id. Jika id tidak ditemukan, balas dengan 404 (Not Found).
  5. deleteUser: Menghapus data user tertentu. Jika data tidak ditemukan, balas dengan 404.

Fungsi-fungsi ini menggunakan callback bawaan dari pool.query. Jika ingin menggunakan pendekatan async/await, kita bisa memanfaatkan pool.promise() dari mysql2.


6. Pengujian Aplikasi CRUD

6.1. Menjalankan Server

Setelah semua file siap, jalankan perintah:

node app.js

Jika ingin agar server otomatis restart ketika ada perubahan kode, bisa memakai nodemon:

npx nodemon app.js

Di terminal, akan muncul pesan semacam:

Server berjalan di port 3000

Itu berarti server sudah aktif.

6.2. Menguji dengan Postman atau cURL

Gunakan alat seperti Postman, Insomnia, atau cURL untuk mengetes setiap endpoint.

  1. Create (POST)

    POST http://localhost:3000/api/users
    Body (JSON):
    {
      "name": "Budi",
      "email": "budi@example.com",
      "age": 25
    }
    

    Jika sukses, respon:

    { "message": "User ditambahkan", "userId": 1 }
    
  2. Read All (GET)

    GET http://localhost:3000/api/users
    

    Respon (contoh):

    [
      {
        "id": 1,
        "name": "Budi",
        "email": "budi@example.com",
        "age": 25
      }
    ]
    
  3. Read by ID (GET)

    GET http://localhost:3000/api/users/1
    

    Respon (contoh):

    {
      "id": 1,
      "name": "Budi",
      "email": "budi@example.com",
      "age": 25
    }
    
  4. Update (PUT)

    PUT http://localhost:3000/api/users/1
    Body (JSON):
    {
      "name": "Budi Sukamto",
      "email": "budi_s@example.com",
      "age": 26
    }
    

    Respon (contoh):

    { "message": "User diperbarui" }
    
  5. Delete (DELETE)

    DELETE http://localhost:3000/api/users/1
    

    Respon (contoh):

    { "message": "User dihapus" }
    

Jika setiap endpoint bekerja dengan benar, artinya proses CRUD berhasil.


7. Tips dan Peningkatan

  1. Validasi Input
    Gunakan library seperti joi atau express-validator untuk memvalidasi data yang dikirim oleh klien. Ini mencegah data tidak valid masuk ke database.

  2. Struktur MVC atau Clean Architecture
    Untuk aplikasi berskala besar, pertimbangkan membuat lapisan service atau repository agar logika bisnis lebih terpisah dari logika database.

  3. Error Handling Lebih Lanjut
    Buat error middleware khusus di Express. Dengan begitu, penanganan error lebih terorganisir. Contoh:

    app.use((err, req, res, next) => {
      console.error(err.stack);
      res.status(500).json({ error: 'Terjadi masalah pada server' });
    });
    
  4. Penggunaan ORM
    Jika ingin lebih fleksibel atau memakai fitur migrations, gunakan ORM seperti Sequelize, TypeORM (untuk TS), atau Prisma. ORM sering memudahkan dalam mengelola relasi tabel dan migrasi skema database.

  5. Keamanan

    • Pastikan tidak pernah membocorkan kredensial database di repositori publik.
    • Selalu filter input agar tidak rentan terhadap SQL Injection. Meskipun mysql2 mendukung prepared statements lewat parameter array, tetap berhati-hati.
    • Pertimbangkan untuk menambahkan autentikasi & otorisasi (JWT atau session) jika aplikasi memerlukan akses terbatas.
  6. Menerapkan ke Produksi

    • Gunakan platform seperti Heroku, Railway, AWS, atau VPS.
    • Pakai pm2 atau sistem process manager lain untuk menjaga agar Node.js tetap berjalan.
    • Tambahkan SSL (HTTPS) agar data yang dikirim lebih aman.

8. Mengadaptasi ke MongoDB

Jika lebih suka database NoSQL seperti MongoDB, alurnya masih serupa:

  1. Install mongoose.
  2. Buat file koneksi db.js menggunakan mongoose.connect.
  3. Definisikan schema dan model di folder models/.
  4. Ganti logika controller agar menggunakan method Mongoose (Model.find, Model.create, dll.) dibanding query SQL.

Contoh koneksi db.js dengan MongoDB Atlas:

require('dotenv').config();
const mongoose = require('mongoose');

mongoose.connect(process.env.MONGO_URI, {
  useNewUrlParser: true,
  useUnifiedTopology: true
})
.then(() => console.log('Terhubung ke MongoDB'))
.catch(err => console.error('Gagal terkoneksi ke MongoDB:', err));

module.exports = mongoose;

Setelah itu, kita bisa membuat file userModel.js:

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  name: String,
  email: String,
  age: Number
});

module.exports = mongoose.model('User', userSchema);

Sedangkan di controller, kita tinggal panggil User.create, User.find(), User.findById, User.findByIdAndUpdate, dsb.


9. Contoh Penggunaan di Frontend

Jika ingin memanggil API CRUD ini dari aplikasi frontend (misal React, Vue, atau Angular), cukup arahkan request ke endpoint yang telah dibuat. Contohnya, di React:

// Mengambil daftar pengguna
fetch('http://localhost:3000/api/users')
  .then(response => response.json())
  .then(data => console.log(data));

// Menambahkan pengguna baru
fetch('http://localhost:3000/api/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'Andi', email: 'andi@example.com', age: 23 })
})
.then(response => response.json())
.then(result => console.log(result));

Struktur respons yang dikembalikan server akan sama seperti pengujian manual di Postman.


10. Ringkasan Alur

  1. Inisialisasi Proyek: Buat folder, jalankan npm init -y, install dependencies.
  2. Struktur Direktori: Pisahkan file koneksi database, routes, controller, dan file utama app.js.
  3. Konfigurasi Database: Lengkapi file .env untuk menyimpan detail koneksi.
  4. Definisikan Routes: Pada routes/userRoutes.js, buat rute untuk POST, GET, PUT, dan DELETE.
  5. Implementasi Controller: Di controllers/userController.js, buat fungsi untuk tiap operasi CRUD. Lakukan query ke database.
  6. Jalankan dan Uji: Gunakan Postman atau cURL untuk memastikan semua rute berjalan sesuai harapan.
  7. Pengembangan Lanjutan: Tambahkan validasi, autentikasi, dan model data yang lebih kompleks. Pertimbangkan ORM atau library lain sesuai kebutuhan.

Baca Juga :