Cara Membuat Fitur Like dan Bookmark di Aplikasi Web: Panduan Backend API Lengkap untuk Developer

Fitur Like dan Bookmark sudah jadi standar di hampir semua aplikasi modern, mulai dari media sosial, e-commerce, hingga platform berita. Bagi seorang developer, membangun fitur ini memang terlihat sederhana di permukaan, tapi sebenarnya ada banyak pertimbangan teknis di baliknya, terutama di sisi backend API dan desain database. Jika kita tidak merancangnya dengan baik, masalah skalabilitas, performa, dan keamanan bisa jadi momok di kemudian hari.

Artikel ini akan memandu Anda secara mendalam tentang bagaimana cara membangun fitur Like dan Bookmark yang robust untuk aplikasi web. Kita akan fokus pada sisi backend API menggunakan Node.js dan Express.js, dengan PostgreSQL sebagai database. Tujuannya bukan cuma bisa jalan, tapi juga bisa di-maintain dan di-scale dengan baik di project nyata.

Memahami Konsep Dasar Like dan Bookmark

Sebelum masuk ke kode, penting untuk memahami perbedaan fundamental dan bagaimana kita akan memodelkannya dalam database.

Fitur Like

Fitur Like (atau Upvote, Favorit) adalah cara bagi pengguna untuk mengekspresikan apresiasi atau persetujuan terhadap suatu konten. Karakteristik utamanya:

  • Satu kali per pengguna per konten: Seorang pengguna hanya bisa me-like satu konten satu kali. Jika di-like lagi, biasanya akan dibatalkan (unlike).
  • Tidak perlu menyimpan detail konten: User tidak perlu “mengakses kembali” konten yang di-like dari daftar like mereka. Tujuan utamanya adalah agregasi (berapa banyak like).
  • Dapat dibatalkan: User bisa membatalkan like kapan saja.

Fitur Bookmark

Fitur Bookmark (atau Simpan, Favorit) adalah cara bagi pengguna untuk menyimpan konten tertentu agar bisa diakses kembali dengan mudah di kemudian hari. Karakteristik utamanya:

  • Satu kali per pengguna per konten: Mirip dengan like, seorang pengguna hanya bisa membookmark satu konten satu kali.
  • Perlu menyimpan detail konten atau referensi: User ingin melihat daftar konten yang telah mereka bookmark, jadi kita perlu menyimpan referensi ke konten tersebut.
  • Dapat dibatalkan: User bisa menghapus bookmark kapan saja.

Desain Data Model untuk Like dan Bookmark

Struktur database adalah jantung dari fitur ini. Kita akan menggunakan pendekatan relasional dengan PostgreSQL. Mari asumsikan kita memiliki tabel users dan posts (atau artikel, produk, dll).

Tabel users

Representasi dasar untuk pengguna aplikasi. Setiap pengguna memiliki ID unik.

  • id (UUID/Integer, Primary Key)
  • username (VARCHAR)
  • email (VARCHAR)

Tabel posts

Representasi dasar untuk konten yang bisa di-like atau di-bookmark.

  • id (UUID/Integer, Primary Key)
  • title (VARCHAR)
  • content (TEXT)
  • author_id (UUID/Integer, Foreign Key ke users.id)

Tabel likes

Tabel pivot (many-to-many) untuk menghubungkan pengguna dengan postingan yang mereka like. Setiap baris merepresentasikan satu like.

  • user_id (UUID/Integer, Foreign Key ke users.id)
  • post_id (UUID/Integer, Foreign Key ke posts.id)
  • created_at (TIMESTAMP)
  • Primary Key: Kombinasi (user_id, post_id) untuk memastikan setiap user hanya bisa like satu post sekali.

Tabel bookmarks

Mirip dengan likes, ini juga tabel pivot many-to-many.

  • user_id (UUID/Integer, Foreign Key ke users.id)
  • post_id (UUID/Integer, Foreign Key ke posts.id)
  • created_at (TIMESTAMP)
  • Primary Key: Kombinasi (user_id, post_id) untuk memastikan setiap user hanya bisa bookmark satu post sekali.

Dengan desain ini, kita bisa dengan mudah mencari semua post yang di-like/di-bookmark oleh user tertentu, atau berapa banyak like/bookmark yang dimiliki suatu post.

Persiapan Lingkungan Pengembangan

Kita akan menggunakan Node.js dan Express.js untuk backend, serta PostgreSQL sebagai database. Pastikan Anda sudah menginstal hal-hal berikut:

  • Node.js dan npm (atau Yarn)
  • PostgreSQL server
  • SQL Client seperti DBeaver, pgAdmin, atau command line psql

Inisialisasi Proyek Node.js

Buat folder proyek baru dan inisialisasi:

mkdir like-bookmark-api

cd like-bookmark-api

npm init -y

Instalasi Dependensi

Instal Express.js untuk kerangka kerja web, pg untuk koneksi PostgreSQL, dan dotenv untuk mengelola environment variables.

npm install express pg dotenv

Konfigurasi Database

Buat database baru di PostgreSQL Anda (misalnya, like_bookmark_db). Kemudian, buat file .env di root proyek Anda:

DB_USER=your_username

DB_HOST=localhost

DB_DATABASE=like_bookmark_db

DB_PASSWORD=your_password

DB_PORT=5432

Pastikan untuk mengganti placeholder dengan kredensial PostgreSQL Anda.

Membuat Skema Database

Kita bisa menjalankan skrip SQL ini di SQL client Anda untuk membuat tabel yang dibutuhkan:


CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    username VARCHAR(255) UNIQUE NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE posts (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    title VARCHAR(255) NOT NULL,
    content TEXT,
    author_id UUID REFERENCES users(id) ON DELETE CASCADE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE likes (
    user_id UUID REFERENCES users(id) ON DELETE CASCADE,
    post_id UUID REFERENCES posts(id) ON DELETE CASCADE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (user_id, post_id)
);

CREATE TABLE bookmarks (
    user_id UUID REFERENCES users(id) ON DELETE CASCADE,
    post_id UUID REFERENCES posts(id) ON DELETE CASCADE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (user_id, post_id)
);

Catatan: Kita menggunakan gen_random_uuid() untuk ID UUID otomatis. Jika PostgreSQL Anda tidak mendukung ini (versi sangat lama), Anda bisa menggunakan integer ID dengan SERIAL PRIMARY KEY dan mengelola ID di aplikasi.

Membangun Backend API dengan Node.js dan Express.js

Sekarang, mari kita bangun API-nya.

Struktur Proyek

Agar lebih terorganisir, kita bisa menggunakan struktur dasar ini:


like-bookmark-api/
├── .env
├── package.json
├── server.js
├── db.js
└── routes/
    ├── posts.js
    └── users.js

db.js: Koneksi Database

File ini akan mengelola koneksi ke PostgreSQL.


require('dotenv').config();
const { Pool } = require('pg');

const pool = new Pool({
    user: process.env.DB_USER,
    host: process.env.DB_HOST,
    database: process.env.DB_DATABASE,
    password: process.env.DB_PASSWORD,
    port: process.env.DB_PORT,
});

pool.on('error', (err, client) => {
    console.error('Unexpected error on idle client', err);
    process.exit(-1);
});

module.exports = {
    query: (text, params) => pool.query(text, params),
    getClient: () => pool.connect(),
};

routes/posts.js: API untuk Post, Like, dan Bookmark

Di sini kita akan mendefinisikan endpoint untuk mengelola postingan, serta menambahkan dan menghapus like/bookmark.


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

// --- POSTS ---
// Untuk demo, kita asumsikan user_id didapat dari middleware autentikasi
// Di sini kita pakai user_id dummy
const DUMMY_USER_ID = '0a1b2c3d-e4f5-6789-abcd-ef0123456789'; // Ganti dengan UUID user yang valid di DB Anda

// GET semua post
router.get('/', async (req, res) => {
    try {
        const { rows } = await db.query('SELECT * FROM posts ORDER BY created_at DESC');
        res.json(rows);
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Internal Server Error' });
    }
});

// GET post berdasarkan ID
router.get('/:id', async (req, res) => {
    const { id } = req.params;
    try {
        const { rows } = await db.query('SELECT * FROM posts WHERE id = $1', [id]);
        if (rows.length === 0) {
            return res.status(404).json({ error: 'Post not found' });
        }
        res.json(rows[0]);
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Internal Server Error' });
    }
});

// POST post baru (membutuhkan user_id asli dari auth)
router.post('/', async (req, res) => {
    const { title, content } = req.body;
    // Asumsikan user_id datang dari token autentikasi. Untuk demo, pakai DUMMY_USER_ID.
    const authorId = DUMMY_USER_ID; 

    if (!title || !content || !authorId) {
        return res.status(400).json({ error: 'Title, content, and author_id are required' });
    }

    try {
        const { rows } = await db.query(
            'INSERT INTO posts (title, content, author_id) VALUES ($1, $2, $3) RETURNING *',
            [title, content, authorId]
        );
        res.status(201).json(rows[0]);
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Internal Server Error' });
    }
});

// --- LIKES ---

// POST untuk menambah like
router.post('/:id/like', async (req, res) => {
    const { id: postId } = req.params;
    // Asumsikan user_id datang dari token autentikasi
    const userId = DUMMY_USER_ID; 

    try {
        const { rows } = await db.query(
            'INSERT INTO likes (user_id, post_id) VALUES ($1, $2) ON CONFLICT (user_id, post_id) DO NOTHING RETURNING *',
            [userId, postId]
        );
        if (rows.length > 0) {
            res.status(201).json({ message: 'Post liked', like: rows[0] });
        } else {
            res.status(200).json({ message: 'Post already liked' });
        }
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Internal Server Error' });
    }
});

// DELETE untuk menghapus like
router.delete('/:id/like', async (req, res) => {
    const { id: postId } = req.params;
    const userId = DUMMY_USER_ID;

    try {
        const { rowCount } = await db.query(
            'DELETE FROM likes WHERE user_id = $1 AND post_id = $2',
            [userId, postId]
        );
        if (rowCount === 0) {
            return res.status(404).json({ error: 'Like not found' });
        }
        res.status(200).json({ message: 'Post unliked' });
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Internal Server Error' });
    }
});

// GET jumlah like untuk sebuah post
router.get('/:id/likes/count', async (req, res) => {
    const { id: postId } = req.params;
    try {
        const { rows } = await db.query('SELECT COUNT(*) FROM likes WHERE post_id = $1', [postId]);
        res.json({ count: parseInt(rows[0].count, 10) });
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Internal Server Error' });
    }
});

// --- BOOKMARKS ---

// POST untuk menambah bookmark
router.post('/:id/bookmark', async (req, res) => {
    const { id: postId } = req.params;
    const userId = DUMMY_USER_ID;

    try {
        const { rows } = await db.query(
            'INSERT INTO bookmarks (user_id, post_id) VALUES ($1, $2) ON CONFLICT (user_id, post_id) DO NOTHING RETURNING *',
            [userId, postId]
        );
        if (rows.length > 0) {
            res.status(201).json({ message: 'Post bookmarked', bookmark: rows[0] });
        } else {
            res.status(200).json({ message: 'Post already bookmarked' });
        }
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Internal Server Error' });
    }
});

// DELETE untuk menghapus bookmark
router.delete('/:id/bookmark', async (req, res) => {
    const { id: postId } = req.params;
    const userId = DUMMY_USER_ID;

    try {
        const { rowCount } = await db.query(
            'DELETE FROM bookmarks WHERE user_id = $1 AND post_id = $2',
            [userId, postId]
        );
        if (rowCount === 0) {
            return res.status(404).json({ error: 'Bookmark not found' });
        }
        res.status(200).json({ message: 'Post unbookmarked' });
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Internal Server Error' });
    }
});

module.exports = router;

Penting: Kode di atas menggunakan DUMMY_USER_ID. Dalam aplikasi nyata, userId ini harus didapatkan dari token autentikasi (misalnya, JWT) setelah user login. Anda akan memerlukan middleware autentikasi untuk ini.

routes/users.js: API untuk User dan Daftar Bookmark Mereka

Endpoint untuk mengambil daftar bookmark seorang user.


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

// Untuk demo, kita asumsikan user_id didapat dari middleware autentikasi
// Di sini kita pakai user_id dummy
const DUMMY_USER_ID = '0a1b2c3d-e4f5-6789-abcd-ef0123456789'; 

// GET user berdasarkan ID (opsional, untuk demo)
router.get('/:id', async (req, res) => {
    const { id } = req.params;
    try {
        const { rows } = await db.query('SELECT id, username, email, created_at FROM users WHERE id = $1', [id]);
        if (rows.length === 0) {
            return res.status(404).json({ error: 'User not found' });
        }
        res.json(rows[0]);
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Internal Server Error' });
    }
});

// GET daftar bookmark untuk user tertentu (membutuhkan user_id asli dari auth)
router.get('/:userId/bookmarks', async (req, res) => {
    const { userId } = req.params; // Dalam aplikasi nyata, ini bisa jadi ID user dari token autentikasi
    // Atau bisa juga hardcode DUMMY_USER_ID jika user idnya selalu sama
    // const userId = DUMMY_USER_ID; 
    
    try {
        const { rows } = await db.query(
            `SELECT p.id, p.title, p.content, p.created_at, u.username as author_username
             FROM bookmarks b
             JOIN posts p ON b.post_id = p.id
             JOIN users u ON p.author_id = u.id
             WHERE b.user_id = $1
             ORDER BY b.created_at DESC`,
            [userId]
        );
        res.json(rows);
    } catch (err) {
        console.error(err);
        res.status(500).json({ error: 'Internal Server Error' });
    }
});

module.exports = router;

server.js: File Utama Aplikasi

Ini adalah file utama yang akan menjalankan server Express.js.


require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const postRoutes = require('./routes/posts');
const userRoutes = require('./routes/users');
const db = require('./db'); // Pastikan koneksi DB tersedia

const app = express();
const PORT = process.env.PORT || 3000;

app.use(bodyParser.json());

// Contoh middleware untuk "autentikasi" dummy
// Di aplikasi nyata, ini akan memvalidasi token JWT dan mengambil user ID
app.use((req, res, next) => {
    // Untuk demo, kita selalu set req.user.id ke dummy ID
    // Di produksi, Anda akan mengekstrak user ID dari JWT atau session
    req.user = { id: process.env.DUMMY_USER_ID || '0a1b2c3d-e4f5-6789-abcd-ef0123456789' }; 
    next();
});

// Gunakan routes
app.use('/api/posts', postRoutes);
app.use('/api/users', userRoutes);

// Root route
app.get('/', (req, res) => {
    res.send('Welcome to Like & Bookmark API');
});

// Jalankan server
app.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`);
});

Untuk menjalankan server, buka terminal di root proyek dan ketik:

node server.js

Server akan berjalan di http://localhost:3000.

Pertimbangan Penting untuk Produksi

Implementasi di atas adalah fondasi. Untuk aplikasi skala produksi, ada beberapa hal krusial yang perlu diperhatikan:

Autentikasi dan Otorisasi

Seperti yang disinggung, DUMMY_USER_ID tidak boleh digunakan di produksi. Anda perlu sistem autentikasi (misalnya, JWT) untuk memverifikasi identitas pengguna dan middleware otorisasi untuk memastikan pengguna hanya bisa melakukan operasi yang diizinkan (misalnya, hanya me-like atau membookmark sebagai diri mereka sendiri).

Skalabilitas

  • Indeks Database: Pastikan kolom user_id dan post_id pada tabel likes dan bookmarks terindeks dengan baik untuk query yang cepat. PostgreSQL secara otomatis membuat indeks untuk Primary Key.
  • Caching Jumlah Like: Untuk post dengan jumlah like sangat banyak yang sering diakses, menghitung COUNT(*) setiap saat bisa mahal. Anda bisa menyimpan jumlah like di kolom terpisah pada tabel posts dan mengupdatenya setiap kali ada like/unlike. Atau gunakan Redis untuk caching yang lebih cepat.

Race Conditions

Ketika banyak user me-like atau un-like post yang sama secara bersamaan, bisa terjadi “race condition”. Contoh, dua user me-like bersamaan, jika tidak ditangani dengan baik, bisa ada dua entry like, atau salah satu like gagal. Klausa ON CONFLICT DO NOTHING di PostgreSQL yang kita gunakan sudah membantu mencegah duplikasi like/bookmark.

Keamanan

Selalu gunakan parameterized query (seperti db.query(text, params) yang kita gunakan) untuk mencegah SQL Injection. Validasi input dari user juga sangat penting.

Pengujian

Tulis unit tests dan integration tests untuk API Anda. Pastikan semua endpoint berfungsi sesuai harapan dan menangani error dengan benar.

Masalah yang Sering Terjadi

Dalam mengembangkan fitur Like dan Bookmark, beberapa masalah umum sering muncul:

1. Duplikasi Like/Bookmark

Gejala: Seorang pengguna bisa me-like atau membookmark konten yang sama berkali-kali, menghasilkan entri ganda di database.

Penyebab: Kurangnya constraint unik pada kombinasi (user_id, post_id) di tabel likes dan bookmarks, atau logika aplikasi tidak memeriksa keberadaan like/bookmark sebelum menambahkannya.

Solusi: Kita sudah mengimplementasikan PRIMARY KEY (user_id, post_id) dan ON CONFLICT (user_id, post_id) DO NOTHING di PostgreSQL. Ini memastikan tidak ada duplikasi. Pastikan ini ada di skema database Anda.

2. Performa Menurun saat Menghitung Like/Bookmark

Gejala: Aplikasi lambat saat menampilkan jumlah like atau daftar bookmark, terutama pada konten atau user dengan data sangat banyak.

Penyebab: Query COUNT(*) atau JOIN tabel besar secara berulang tanpa indeks yang memadai, atau database yang tidak dioptimalkan.

Solusi: Pastikan ada indeks pada kolom user_id dan post_id di tabel likes dan bookmarks. Untuk jumlah like/bookmark yang sangat sering diakses, pertimbangkan:

  • Caching: Simpan jumlah total like di kolom like_count di tabel posts. Update kolom ini setiap kali like/unlike terjadi.
  • Redis: Gunakan Redis untuk caching jumlah like yang sangat dinamis.

3. Masalah Autentikasi dan Otorisasi

Gejala: Pengguna bisa me-like atau membookmark sebagai user lain, atau bahkan tanpa identitas yang jelas.

Penyebab: Tidak adanya middleware autentikasi yang memadai untuk memvalidasi user, atau tidak ada otorisasi untuk memastikan user yang melakukan aksi adalah user yang bersangkutan.

Solusi: Implementasikan sistem autentikasi yang robust (misalnya JWT atau Session-based). Pastikan user_id yang digunakan dalam operasi like/bookmark selalu berasal dari user yang sudah terautentikasi, bukan dari input body request.

Pengalaman dan Pertimbangan Praktis

Dalam mengembangkan fitur seperti ini di project nyata, saya sering menemukan beberapa trade-off dan detail yang penting:

Pemilihan Database: Relasional vs. NoSQL

Untuk fitur like dan bookmark, database relasional seperti PostgreSQL yang kita gunakan ini adalah pilihan yang sangat solid. Relasi antara user dan post terdefinisi dengan jelas, dan constraint seperti PRIMARY KEY (user_id, post_id) sangat membantu integritas data.

Jika Anda mempertimbangkan NoSQL (seperti MongoDB), Anda mungkin akan membuat dokumen post yang berisi array likers atau bookmarkers. Ini bisa lebih fleksibel untuk skema yang berubah-ubah, tetapi untuk pencarian dan agregasi yang kompleks, Anda perlu mengelola indeks secara manual dan mungkin menghadapi tantangan performa jika array-nya menjadi sangat besar (banyak sekali like/bookmark). Untuk data relasional yang jelas seperti ini, SQL seringkali lebih terstruktur dan efisien dalam jangka panjang.

Notifikasi Real-time

Pada aplikasi media sosial modern, ketika seseorang me-like postingan Anda, Anda sering mendapatkan notifikasi secara real-time. Implementasi ini membutuhkan teknologi seperti WebSockets (misalnya dengan Socket.IO di Node.js). Setelah API like/bookmark berhasil, Anda bisa memancarkan event WebSocket ke klien yang relevan (misalnya, pemilik post yang di-like) untuk memberikan update real-time.

Analytics dan Metrik

Fitur like dan bookmark adalah sumber data berharga untuk analitik. Anda bisa melacak popularitas konten, tren preferensi pengguna, atau bahkan menggunakan data ini untuk rekomendasi konten. Memastikan tabel memiliki kolom created_at (seperti yang kita lakukan) sangat membantu untuk analisis berbasis waktu.

Biaya dan Resource

Untuk aplikasi kecil atau MVP, setup yang kita gunakan (Node.js + PostgreSQL di satu VPS) sudah lebih dari cukup. Namun, untuk skala besar, Anda mungkin perlu:

  • Database Terpisah: Memisahkan database utama dari database analitik, atau menggunakan replikasi (read replicas) untuk query baca yang intensif.
  • Caching Layer: Menambahkan Redis di depan database untuk mengurangi beban pada database, terutama untuk operasi baca yang sering (misalnya, jumlah like).
  • Server Lebih Kuat/Cloud Native: Migrasi ke cloud provider (AWS, GCP, Azure) dengan layanan database terkelola (RDS, Cloud SQL) dan scaling otomatis.

Perlu diingat, setiap fitur baru menambah beban pada infrastruktur. Perencanaan awal yang baik akan menghemat banyak waktu dan biaya di masa depan.

FAQ

Apakah saya perlu tabel terpisah untuk like dan bookmark?

Ya, disarankan untuk memiliki tabel terpisah (likes dan bookmarks). Meskipun strukturnya mirip, tujuan fungsionalitasnya berbeda. Memisahkan mereka memudahkan query, pemeliharaan, dan skalabilitas di masa depan. Jika keduanya digabung, Anda akan memerlukan kolom ‘type’ (misalnya, ‘like’ atau ‘bookmark’), yang bisa mempersulit indexing dan query di kemudian hari.

Bagaimana cara menghitung total like dengan efisien?

Cara paling langsung adalah menggunakan SELECT COUNT(*) FROM likes WHERE post_id = [ID]. Namun, untuk performa lebih baik di aplikasi skala besar, Anda bisa menyimpan jumlah like di kolom terpisah (misalnya, like_count) di tabel posts. Update kolom ini menggunakan trigger database atau query aplikasi setiap kali like/unlike terjadi. Untuk caching yang lebih agresif, gunakan Redis.

Apa bedanya like dan vote up?

Secara teknis, keduanya mirip dalam implementasi database: user_id dan item_id. Perbedaannya lebih pada konteks UX dan fungsionalitas. “Like” umumnya menunjukkan apresiasi, sedangkan “Vote Up” seringkali dikombinasikan dengan “Vote Down” untuk sistem rating atau sorting berdasarkan popularitas, seperti di Reddit atau Stack Overflow. Sistem voting seringkali memiliki aturan lebih kompleks (misalnya, user reputasi memengaruhi bobot vote).

Bagaimana cara mengimplementasikan fitur like/bookmark di frontend?

Di frontend (misalnya, dengan React, Vue, atau Svelte), Anda akan memanggil API yang sudah kita buat ini. Ketika user mengklik tombol “Like”, Anda panggil POST /api/posts/:id/like. Jika user mengklik lagi, Anda panggil DELETE /api/posts/:id/like. Status tombol (sudah di-like/belum) dapat diperoleh dengan memeriksa apakah user saat ini memiliki entri di tabel like untuk post tersebut, atau dari data yang dikirimkan bersama post (misalnya, kolom is_liked_by_current_user yang dihitung di backend).

Kesimpulan

Membangun fitur Like dan Bookmark adalah langkah esensial dalam menciptakan aplikasi web yang interaktif dan menarik. Meskipun terlihat sederhana, desain backend API dan database yang tepat adalah kunci untuk memastikan fitur ini bisa diskalakan, performanya baik, dan aman. Dengan Node.js, Express.js, dan PostgreSQL, kita telah melihat bagaimana membangun fondasi yang kokoh.

Ingatlah bahwa contoh ini adalah titik awal. Dalam aplikasi produksi, Anda perlu menambahkan lapisan autentikasi, validasi input yang lebih kuat, penanganan error yang lebih komprehensif, dan mungkin strategi caching untuk performa optimal. Teruslah bereksperimen, belajar dari implementasi nyata, dan jangan ragu untuk mengadaptasi pendekatan ini sesuai dengan kebutuhan spesifik proyek Anda.

TAGS: Node.js, Express.js, PostgreSQL, Backend API, Web Development, Programming Tutorial, Database Design, Feature Development, Software Engineering, Developer Workflow


Baca Juga

You May Also Like

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *