kodingup.camp

Beranda/Node.js Backend: Dasar, Express & REST API

Apa itu Backend & Node.js

Modul 1 dari 105 menit bacaWhat is Backend and Node.js

Isi modul

    Kenapa ini penting

    Sebagai frontend developer, kamu sudah sering memanggil fetch("/api/..."). Tapi selama kamu tidak paham apa yang terjadi di ujung sana, setiap error terasa seperti kotak hitam: kenapa dapat 401? Kenapa request kadang lama? Kenapa data yang kamu kirim tidak tersimpan? Memahami backend membuatmu bisa membaca masalah dari dua sisi, dan itu yang membedakan developer junior dari developer yang bisa dipercaya memegang fitur dari awal sampai akhir.

    Selain itu, backend adalah tempat aturan bisnis yang sebenarnya tinggal. Validasi di form React bisa dilewati siapa saja yang membuka DevTools atau memakai curl. Validasi di server tidak bisa. Harga, stok, hak akses, dan password semuanya harus diputuskan di backend.

    Konsep inti

    Client dan server

    Bayangkan sebuah warung makan. Kamu (pelanggan) duduk di meja dan memesan lewat pelayan. Pelayan membawa pesananmu ke dapur, dapur memasak, lalu pelayan mengantar makanan ke mejamu. Dalam dunia web:

    Server tidak pernah "menelepon" client duluan dalam HTTP biasa. Selalu client yang bertanya, server yang menjawab. Pola ini disebut request/response.

    Anatomi request dan response HTTP

    Setiap request HTTP berisi:

    Bagian Contoh Fungsi
    Method GET, POST, PATCH, DELETE Jenis aksi yang diminta
    URL / path /api/v1/tugas?selesai=true Sumber daya yang dituju, plus query string
    Headers Content-Type: application/json Informasi tambahan (format data, token login, bahasa)
    Body {"judul":"Belajar Node"} Data yang dikirim (biasanya untuk POST/PUT/PATCH)

    Response dari server berisi:

    Bagian Contoh Fungsi
    Status code 200, 201, 404, 500 Ringkasan hasil dalam bentuk angka
    Headers Content-Type: application/json; charset=utf-8 Info tentang isi jawaban
    Body {"data":[...]} Isi jawaban: JSON, HTML, gambar, dan lain-lain

    Kamu bisa melihat semuanya langsung dengan curl -i, yang menampilkan header response. Ini salah satu kebiasaan terpenting backend developer: jangan menebak, lihat request dan response aslinya.

    Node.js itu apa?

    Node.js adalah runtime JavaScript di luar browser. Mesinnya sama dengan Chrome (V8), tapi alih-alih punya document dan window, Node punya akses ke file, jaringan, proses, dan sistem operasi. Jadi bahasa yang sudah kamu kuasai untuk React bisa langsung dipakai untuk menulis server.

    Yang membuat Node khas adalah model event loop dengan I/O non-blocking. Analogi warung tadi: satu pelayan super cepat (thread JavaScript) melayani banyak meja. Saat pelanggan memesan nasi goreng yang butuh 5 menit, pelayan tidak berdiri menunggu di depan kompor. Dia menitipkan pesanan ke dapur (sistem operasi atau thread pool), lalu langsung melayani meja lain. Begitu dapur selesai, ada "bel" (callback/Promise selesai) dan pelayan mengantar hasilnya.

    Pekerjaan yang "menunggu" disebut I/O: membaca file, query database, memanggil API lain, menerima data jaringan. Backend web kebanyakan isinya I/O, makanya satu proses Node bisa melayani ribuan koneksi dengan memori kecil.

    Kelemahannya: kalau pelayan sendiri yang disuruh mengerjakan sesuatu yang berat (menghitung jutaan angka, mengompres gambar besar secara sinkron), semua meja lain ikut menunggu. Ini disebut memblokir event loop. Contoh kodenya ada di bawah.

    Node vs PHP, Python, Go

    Runtime Gaya umum Kelebihan Catatan
    Node.js Satu thread JS + event loop, async/await Satu bahasa dengan frontend, ekosistem npm terbesar, cocok untuk API dan real-time Kurang cocok untuk komputasi CPU berat di thread utama
    PHP Umumnya satu proses/worker per request Hosting murah dan di mana-mana, Laravel sangat produktif Model async tidak sepopuler di Node
    Python Django/FastAPI, sinkron atau async Sangat kuat di data science dan AI Perlu pilih jalur sync atau async sejak awal
    Go Goroutine ringan, dikompilasi Performa tinggi, binary tunggal, konkurensi bawaan Bahasa baru lagi untuk dipelajari

    Tidak ada yang "paling benar". Untuk kamu yang sudah menguasai JavaScript dan React, Node adalah jalur tercepat menjadi full-stack: tipe data, async/await, fetch, dan bahkan TypeScript bisa dipakai di kedua sisi.

    Contoh kode

    Urutan eksekusi event loop. Simpan sebagai event-loop.js lalu jalankan node event-loop.js.

    // event-loop.js
    import { readFile } from "node:fs/promises";
    
    console.log("1. Mulai");
    setTimeout(() => console.log("Timer 0 ms selesai"), 0);
    readFile(import.meta.filename, "utf8").then((isi) =>
      console.log(`File terbaca: ${isi.length} karakter`)
    );
    Promise.resolve().then(() => console.log("3. Promise (microtask)"));
    console.log("2. Selesai kode sinkron");
    
    // Output asli (dijalankan 5 kali):
    // → 1. Mulai
    // → 2. Selesai kode sinkron
    // → 3. Promise (microtask)
    // → Timer 0 ms selesai          (4 dari 5 kali muncul duluan)
    // → File terbaca: 349 karakter  (1 dari 5 kali malah lebih dulu dari timer)
    

    Pelajarannya: kode sinkron selalu jalan duluan sampai habis, lalu microtask (Promise), baru callback I/O dan timer. Urutan antara timer dan I/O tidak dijamin, jadi jangan pernah menulis kode yang bergantung pada urutan itu.

    Sekarang lihat bahayanya memblokir event loop:

    // blocking.js
    import http from "node:http";
    
    http.createServer((req, res) => {
      if (req.url === "/berat") {
        const mulai = Date.now();
        while (Date.now() - mulai < 3000) {} // CPU sibuk 3 detik: memblokir SEMUA request
        return res.end("berat selesai\n");
      }
      res.end("ringan\n");
    }).listen(process.env.PORT ?? 3000);
    
    node blocking.js
    # Terminal lain: panggil /berat, lalu 0,2 detik kemudian panggil /ringan
    curl -s localhost:3000/berat > /dev/null &
    sleep 0.2; time curl -s localhost:3000/ringan
    # → ringan
    # → real 2.79   ← request "ringan" ikut menunggu hampir 3 detik!
    

    Request /ringan seharusnya instan, tapi harus antre karena satu-satunya thread JavaScript sedang sibuk berputar di while. Di server sungguhan, ini berarti semua pengguna merasakan aplikasi "hang".

    Kesalahan umum

    1. Mengira Node itu bahasa pemrograman. Bahasanya tetap JavaScript; Node adalah lingkungan tempat JavaScript berjalan, sama seperti browser.
    2. Memakai fungsi sinkron berat di dalam handler request. Misalnya readFileSync untuk file besar atau perulangan raksasa. Gunakan versi async (node:fs/promises), dan untuk komputasi berat pertimbangkan worker_threads atau pindahkan ke layanan lain.
    3. Bergantung pada urutan setTimeout vs I/O. Seperti terlihat di contoh, urutannya bisa berubah. Kalau butuh urutan, pakai await.
    4. Percaya validasi frontend sudah cukup. Siapa pun bisa mengirim request langsung dengan curl. Server wajib memeriksa ulang semua input.
    5. Memakai window atau document di Node. Objek itu tidak ada. Di Node, globalThis berisi hal seperti process, fetch, setTimeout, dan structuredClone.

    Latihan

    1. Mudah, Jalankan curl -i https://jsonplaceholder.typicode.com/todos/1 lalu tuliskan: status code, nilai header Content-Type, dan isi body-nya.
    2. Sedang, Tulis skrip yang mencetak urutan A (sinkron), B (di dalam queueMicrotask), dan C (di dalam setTimeout). Tebak dulu urutannya sebelum menjalankan.
    3. Menantang, Ubah blocking.js agar route /berat tidak memblokir request lain, dengan cara membagi pekerjaan menjadi potongan kecil memakai setImmediate (hitung 3 juta angka dalam potongan 100 ribu).
    Lihat solusi

    1. Status 200 OK, Content-Type: application/json; charset=utf-8, body berupa objek todo { "userId": 1, "id": 1, "title": "...", "completed": false }.

    2.

    console.log("A");
    setTimeout(() => console.log("C"), 0);
    queueMicrotask(() => console.log("B"));
    // → A
    // → B
    // → C
    

    3. Kerjakan per potongan, lalu beri kesempatan event loop melayani request lain dengan setImmediate:

    import http from "node:http";
    
    function hitungBertahap(total, ukuran = 100_000) {
      return new Promise((resolve) => {
        let i = 0, jumlah = 0;
        function potong() {
          const batas = Math.min(i + ukuran, total);
          for (; i < batas; i++) jumlah += i;
          if (i < total) setImmediate(potong); // kasih giliran ke request lain
          else resolve(jumlah);
        }
        potong();
      });
    }
    
    http.createServer(async (req, res) => {
      if (req.url === "/berat") {
        const hasil = await hitungBertahap(3_000_000);
        return res.end(`jumlah: ${hasil}\n`);
      }
      res.end("ringan\n");
    }).listen(3000);
    

    Sekarang /ringan langsung dijawab walaupun /berat sedang berjalan.

    Ringkasan

    Video pendamping

    Kalau penjelasan di atas belum masuk, tonton ini. Video dari kanal YouTube pihak lain.

    Node.js Tutorial for Beginners: Learn Node in 1 HourProgramming with Mosh · Bahasa InggrisBuka di YouTube

    Kuis pemahaman

    Pilih satu jawaban per soal. Penjelasan muncul setelah kamu menjawab.