BerandaDatabaseTutorial Node.js + MySQL untuk Aplikasi Real-Time Persisten

Tutorial Node.js + MySQL untuk Aplikasi Real-Time Persisten

Advertisement

Artikel ini merupakan panduan lengkap untuk mengintegrasikan database MySQL ke dalam aplikasi real-time berbasis Node.js dan Socket.io. Anda akan mempelajari langkah-langkah praktis untuk membuat sistem voting yang menyimpan data secara permanen, sehingga informasi tidak hilang meskipun server direstart. Tutorial ini ditujukan bagi developer yang ingin meningkatkan fungsionalitas aplikasi real-time dengan penyimpanan data yang persisten.

Advertisement

Pada tutorial sebelumnya tentang aplikasi real-time dengan Node.js, data hanya disimpan di memori dan akan hilang setelah server dimulai ulang. Untuk kebutuhan produksi, penyimpanan data yang persisten menjadi suatu keharusan. Database MySQL dipilih sebagai solusi karena popularitas dan keandalannya. Oleh karena itu, artikel ini akan membahas integrasi database MySQL untuk membuat aplikasi real-time Node.js yang robust.

Proyek ini merupakan kelanjutan dari tutorial pembuatan aplikasi voting real-time dasar. Pastikan Anda telah menyiapkan lingkungan pengembangan Node.js dan proyek dasarnya sebelum melanjutkan.

Advertisement

Langkah-Langkah Integrasi MySQL ke Aplikasi Real-Time Node.js

Integrasi database melibatkan beberapa langkah kunci yang harus dilakukan secara berurutan. Pertama, pastikan MySQL telah terinstall di sistem Anda. Anda dapat mendownload installer resmi dari situs MySQL. Setelah itu, buat database dan tabel khusus untuk proyek ini.

Advertisement

1. Membuat Skema Tabel Database Voting

Skema tabel menentukan struktur penyimpanan data. Jalankan perintah SQL berikut di client MySQL seperti MySQL Workbench atau phpMyAdmin. Tabel ini akan mencatat setiap vote dengan timestamp otomatis.

CREATE TABLE `voting` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(12) NOT NULL,
  `time` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Penjelasan Skema: Kolom id adalah primary key yang auto-increment. Kolom name menyimpan nama kandidat (misal: “akbar” atau “goldie”). Kolom time mencatat waktu vote secara otomatis. Engine InnoDB dipilih karena mendukung transaksi dan foreign key.

2. Menginstal Driver MySQL untuk Node.js

Node.js memerlukan driver khusus untuk berkomunikasi dengan MySQL. Paket mysql2 lebih direkomendasikan daripada mysql karena mendukung Promise secara native, yang menghasilkan kode yang lebih bersih dan mudah dikelola. Buka terminal di direktori proyek Anda, lalu jalankan perintah berikut.

npm install mysql2

Proses instalasi ini akan menambahkan driver ke dalam file package.json proyek Anda. Pastikan Anda berada di direktori yang sama dengan file server.js saat menjalankan perintah ini.

3. Mengonfigurasi Koneksi Database di server.js

Langkah selanjutnya adalah mengedit file server.js. Buat koneksi pool ke database MySQL menggunakan driver yang sudah diinstal. Konfigurasi pool lebih efisien untuk menangani banyak koneksi secara bersamaan dibandingkan koneksi tunggal.

const mysql = require('mysql2/promise');

// Membuat koneksi pool ke MySQL
const pool = mysql.createPool({
    host: 'localhost',
    user: 'root', // Ganti dengan username MySQL Anda
    password: '', // Ganti dengan password MySQL Anda
    database: 'nama_database_anda', // Ganti dengan nama database
    waitForConnections: true,
    connectionLimit: 10,
    queueLimit: 0
});

Penjelasan Konfigurasi: Opsi connectionLimit: 10 membatasi jumlah koneksi maksimal dalam pool. Opsi waitForConnections: true mengizinkan permintaan menunggu jika pool penuh. Opsi queueLimit: 0 berarti tidak ada batas antrian. Selalu gunakan environment variable untuk menyimpan credential database dalam produksi.

4. Membuat Fungsi untuk Mengambil dan Menyimpan Data

Kode aplikasi memerlukan dua fungsi utama. Fungsi pertama bertugas mengambil data awal saat server berjalan. Fungsi kedua menangani penyimpanan data baru setiap kali pengguna melakukan voting. Penggunaan async/await membuat kode lebih mudah dibaca dibandingkan callback.

// Variabel global untuk data dalam memori
let voteCount = { akbar: 0, goldie: 0 };

// Fungsi inisialisasi data dari database
async function initData() {
    try {
        const [rows] = await pool.query('SELECT `name`, COUNT(*) AS `total` FROM `voting` GROUP BY `name`');
        rows.forEach(row => {
            voteCount[row.name] = row.total;
        });
        console.log('Data berhasil diinisialisasi dari database.');
    } catch (error) {
        console.error('Gagal menginisialisasi data:', error);
    }
}

// Fungsi menambah data voting baru
async function addVote(candidateName) {
    try {
        await pool.query('INSERT INTO voting (name) VALUES (?)', [candidateName]);
        voteCount[candidateName]++;
        return true;
    } catch (error) {
        console.error('Gagal menyimpan vote:', error);
        return false;
    }
}

Detail Fungsi: Fungsi initData() menggunakan query GROUP BY untuk menghitung total vote per kandidat. Hasilnya dimuat ke dalam objek voteCount. Fungsi addVote() menggunakan prepared statement (?) untuk mencegah SQL injection. Kedua fungsi memiliki error handling dasar dengan try-catch.

5. Mengintegrasikan Fungsi Database dengan Socket.io

Integrasi terjadi pada event connection Socket.io. Saat klien terhubung, server mengirim data terbaru. Kemudian, server juga mendengarkan event untuk menambah vote dari klien. Pola ini memastikan semua klien mendapatkan update real-time.

io.on('connection', async (socket) => {
    console.log('Klien terhubung');

    // Kirim data terkini ke klien yang baru terhubung
    socket.emit('updateData', voteCount);

    // Tangani event vote dari klien
    socket.on('submitVote', async (candidate) => {
        const success = await addVote(candidate);
        if (success) {
            // Broadcast data terbaru ke SEMUA klien yang terhubung
            io.emit('updateData', voteCount);
        } else {
            socket.emit('voteError', 'Gagal menyimpan vote.');
        }
    });
});

// Jalankan inisialisasi data saat server start
initData();

Alur Event: Pertama, saat klien terhubung, server mengirim event updateData dengan data terkini. Kedua, ketika klien mengirim event submitVote, server memprosesnya ke database. Jika berhasil, server membroadcast update ke semua klien. Jika gagal, hanya klien pengirim yang mendapat notifikasi error.

6. Optimasi dan Best Practice untuk Produksi

Untuk lingkungan produksi, pertimbangkan beberapa optimasi penting. Pertama, gunakan environment variable untuk menyimpan konfigurasi database. Kedua, implementasikan retry logic untuk koneksi database. Ketiga, pertimbangkan untuk menggunakan Redis cache di depan MySQL jika traffic sangat tinggi.

// Contoh penggunaan environment variable dengan dotenv
require('dotenv').config();
const pool = mysql.createPool({
    host: process.env.DB_HOST,
    user: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_NAME
});

Selain itu, selalu validasi input dari klien sebelum memproses ke database. Untuk aplikasi voting, pastikan nilai kandidat yang diterima sesuai dengan pilihan yang valid.

Dengan mengikuti langkah-langkah di atas, aplikasi real-time Node.js Anda sekarang telah memiliki kemampuan penyimpanan data yang permanen menggunakan database MySQL. Struktur kode menjadi lebih terorganisir dan siap untuk dikembangkan lebih lanjut.

Sebagai langkah berikutnya, Anda dapat menambahkan fitur seperti autentikasi pengguna, logging, atau visualisasi data real-time yang lebih kompleks. Pastikan untuk selalu mengacu pada dokumentasi resmi Node.js dan dokumentasi mysql2 untuk praktik terbaik dan pembaruan. Implementasi ini memberikan fondasi yang solid untuk aplikasi real-time yang membutuhkan persistensi data.

Artikel Terbaru