Pernah nggak kamu selesaikan puluhan tutorial tapi pas ditanya rekruter, "Coba tunjukin project Node.js kamu dong" — kamu malah blank? Kalau iya, artikel ini tepat buat kamu. Di sini kita akan membangun REST API production Node.js yang nyata, bukan sekadar latihan hello world. Ini adalah studi kasus Node.js yang mengintegrasikan Express, JWT authentication, database PostgreSQL, validasi input, error handling, hingga dokumentasi API — semua dalam satu project Node.js lengkap yang siap kamu push ke GitHub dan kamu ceritakan saat interview.
Anggap ini seperti memasak: kamu sudah belajar cara memotong bawang, menumis, sampai cara merebus pasta. Sekarang saatnya kamu masak satu hidangan utuh dari nol — dan hidangan itu adalah REST API yang bisa langsung naik ke production.
Inilah stack minimal yang dibutuhkan sebuah REST API agar layak disebut production-ready. Tidak perlu framework besar — Node.js murni + beberapa library sudah cukup asal kamu tahu cara menggunakannya dengan benar.
🏗️ Arsitektur Project Node.js Lengkap yang Akan Kita Bangun
Sebelum nulis satu baris kode pun, kita harus punya gambaran besarnya dulu. Ini prinsip yang sama seperti arsitek yang bikin cetak biru sebelum tukang bangunan mulai kerja. Proyek kita adalah sebuah API manajemen artikel blog — cocok untuk portfolio karena relate banget sama use case nyata.
my-blog-api/ ├── src/ │ ├── config/ │ │ └── database.js # Koneksi PostgreSQL │ ├── controllers/ │ │ ├── authController.js # Register & Login │ │ └── articleController.js # CRUD artikel │ ├── middlewares/ │ │ ├── authMiddleware.js # Verifikasi JWT │ │ └── validateMiddleware.js # Validasi input │ ├── models/ │ │ ├── userModel.js │ │ └── articleModel.js │ ├── routes/ │ │ ├── authRoutes.js │ │ └── articleRoutes.js │ └── app.js # Entry point ├── .env ├── .gitignore ├── package.json └── README.md
Pisahkan logika bisnis (controllers) dari akses database (models) dan routing (routes). Pola ini disebut MVC (Model-View-Controller) dan membuat kode kamu jauh lebih mudah di-maintain dan di-test. Rekruter senior langsung tahu kamu serius kalau melihat struktur seperti ini.
⚙️ Step-by-Step Membangun REST API Production Node.js
Oke, sekarang kita langsung eksekusi. Ikuti langkah-langkah di bawah ini dari awal sampai akhir. Jangan skip — setiap langkah saling terhubung.
Inisialisasi Project & Install Dependencies
# Buat folder dan inisialisasi project mkdir my-blog-api && cd my-blog-api npm init -y # Install dependencies utama npm install express pg bcryptjs jsonwebtoken dotenv cors helmet npm install express-validator # Install dev dependencies npm install --save-dev nodemon
Setup Koneksi Database & File .env
Buat file .env di root project dan file konfigurasi database:
# .env
PORT=3000
DATABASE_URL=postgresql://user:password@localhost:5432/blog_db
JWT_SECRET=your_super_secret_key_min_32_chars
JWT_EXPIRES_IN=7d
NODE_ENV=development
// src/config/database.js const { Pool } = require('pg'); require('dotenv').config(); const pool = new Pool({ connectionString: process.env.DATABASE_URL, ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false }); module.exports = pool;
Jangan pernah hard-code credential database atau JWT secret langsung di kode. Selalu gunakan .env dan pastikan file itu ada di .gitignore. Ini bukan sekadar best practice — ini keamanan dasar yang membedakan developer amatir dan profesional.
Buat Auth Controller dengan JWT
Ini inti dari sistem autentikasi kita. Logika register dan login dengan bcrypt + JWT:
// src/controllers/authController.js const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const pool = require('../config/database'); const register = async (req, res) => { try { const { name, email, password } = req.body; // Cek apakah email sudah ada const existing = await pool.query( 'SELECT id FROM users WHERE email = $1', [email] ); if (existing.rows.length > 0) { return res.status(409).json({ message: 'Email sudah terdaftar' }); } // Hash password const hashedPassword = await bcrypt.hash(password, 12); const result = await pool.query( 'INSERT INTO users (name, email, password) VALUES ($1, $2, $3) RETURNING id, name, email', [name, email, hashedPassword] ); res.status(201).json({ message: 'Registrasi berhasil', user: result.rows[0] }); } catch (err) { res.status(500).json({ message: 'Server error', error: err.message }); } }; module.exports = { register };
Middleware Autentikasi JWT
Middleware ini bertugas sebagai "satpam" yang memeriksa token di setiap request yang butuh autentikasi:
// src/middlewares/authMiddleware.js const jwt = require('jsonwebtoken'); const protect = (req, res, next) => { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ message: 'Token tidak ditemukan' }); } const token = authHeader.split(' ')[1]; try { const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; next(); } catch (err) { res.status(401).json({ message: 'Token tidak valid atau sudah expired' }); } }; module.exports = { protect };
Setup Routes & Main App Entry Point
// src/app.js const express = require('express'); const cors = require('cors'); const helmet = require('helmet'); require('dotenv').config(); const authRoutes = require('./routes/authRoutes'); const articleRoutes = require('./routes/articleRoutes'); const app = express(); // Security middlewares app.use(helmet()); app.use(cors()); app.use(express.json()); // Routes app.use('/api/auth', authRoutes); app.use('/api/articles', articleRoutes); // Global error handler app.use((err, req, res, next) => { console.error(err.stack); res.status(500).json({ message: 'Terjadi kesalahan server' }); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => console.log(`🚀 Server running on port ${PORT}`));
Selalu gunakan helmet() di production untuk mengatur HTTP security headers secara otomatis. Library ini mencegah berbagai serangan umum seperti XSS, clickjacking, dan sniffing. Satu baris kode, perlindungan berlapis.
📊 Endpoint API & Tabel Referensi Lengkap
Dokumentasi endpoint adalah bagian yang sering diabaikan developer pemula. Padahal, ini yang akan dibaca rekan kerja kamu, frontend developer, atau rekruter yang ingin memahami project Node.js lengkap buatanmu.
| Method | Endpoint | Keterangan | Auth? |
|---|---|---|---|
| POST | /api/auth/register | Registrasi user baru | ❌ Tidak |
| POST | /api/auth/login | Login & dapatkan JWT token | ❌ Tidak |
| GET | /api/articles | Ambil semua artikel (pagination) | ❌ Tidak |
| GET | /api/articles/:id | Ambil artikel berdasarkan ID | ❌ Tidak |
| POST | /api/articles | Buat artikel baru | ✅ JWT |
| PUT | /api/articles/:id | Update artikel | ✅ JWT |
| DELETE | /api/articles/:id | Hapus artikel | ✅ JWT |
Menurut Stack Overflow Developer Survey 2024, Node.js adalah runtime paling populer ke-3 di kalangan developer profesional. Project REST API production Node.js seperti ini adalah salah satu hal paling sering diminta dalam technical interview di startup Indonesia. Kamu sudah selangkah lebih dekat!
🔍 Validasi Input & Error Handling — Fondasi API Berkualitas
Perbedaan API amatir dan profesional bukan dari fiturnya, tapi dari bagaimana ia bereaksi saat ada yang salah. Bayangkan kamu memesan kopi di kafe — kalau pesananmu tidak jelas, barista yang baik akan bertanya dengan sopan, bukan diam-diam nuangkan air panas ke cangkir kosong. Begitu juga API yang baik.
Tidak informatif. Developer frontend tidak tahu apa yang harus diperbaiki.
Jelas, spesifik, dan actionable untuk frontend developer.
Implementasi validasi dengan express-validator:
// src/middlewares/validateMiddleware.js const { body, validationResult } = require('express-validator'); const validateRegister = [ body('name').notEmpty().withMessage('Nama wajib diisi'), body('email').isEmail().withMessage('Format email tidak valid'), body('password') .isLength({ min: 8 }) .withMessage('Password minimal 8 karakter'), (req, res, next) => { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(422).json({ success: false, message: 'Validasi gagal', errors: errors.array().map(e => ({ field: e.path, msg: e.msg })) }); } next(); } ]; module.exports = { validateRegister };
Setelah project selesai, buat README.md yang lengkap berisi cara setup, daftar endpoint, contoh request/response, dan cara testing dengan Postman. README yang baik adalah CV kamu. Developer yang tidak punya README di project-nya seperti restoran tanpa menu — orang datang, bingung, terus pergi.
Kamu Sudah Selesai! Ini Bukan Akhir, Ini Awal
Dalam studi kasus ini, kamu sudah membangun project Node.js lengkap berupa REST API production Node.js yang mencakup:
Kamu telah menyelesaikan seluruh seri Node.js from Zero to Zorro. Push project ini ke GitHub, tulis README yang keren, dan ceritakan ini di interview kamu berikutnya. Kamu layak bangga! 🎉
Punya pertanyaan atau ingin berbagi project yang sudah kamu buat? Drop di kolom komentar di bawah — aku baca semuanya! 👇
Node.js from Zero to Zorro
Artikel ini adalah bagian dari seri lengkap belajar Node.js dari nol sampai bisa bangun aplikasi production. Klik tombol di bawah untuk melihat daftar isi lengkapnya.
🗂️ Lihat Daftar Isi Lengkap →seluruh seri Zero to Zorro 🎉