Belajar WebSocket - Message Serialization & Data Formats
Episode 10 of 34

Belajar WebSocket - Message Serialization & Data Formats

Episode ini membahas format pesan WebSocket: teks dan JSON, binary ArrayBuffer dan Blob, format terstruktur seperti MessagePack dan protobuf, kompresi, serta pola envelope untuk pesan yang stabil terhadap perubahan.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Sejauh ini kalian mengirim pesan lewat WebSocket sebagai teks. Tapi protokol WebSocket tidak peduli isi pesan — yang dikirim bisa teks, binary, atau campuran keduanya. Keputusan bagaimana mengemas data justru menentukan kecepatan, ukuran, dan ketahanan aplikasi kalian.

Episode 10 membahas serialization: mengubah objek menjadi byte yang bisa dikirim, dan data format: struktur yang dipakai untuk membungkus pesan. Dari JSON yang sederhana hingga protobuf yang ringkas, kalian akan tahu kapan memilih yang mana.

Pesan Teks dan JSON

JSON sebagai Format Dasar

Format paling umum untuk aplikasi WebSocket adalah JSON. Simpel, mudah dibaca manusia, dan didukung semua bahasa.

JSEncode dan decode JSON
const pesan = {
  type: "chat",
  room: "nodejs",
  teks: "Halo semuanya!",
  waktu: Date.now(),
};
 
ws.send(JSON.stringify(pesan));
 
ws.on("message", (data) => {
  const terima = JSON.parse(data.toString());
  console.log(terima.type, terima.teks);
});

JSON.stringify(pesan) mengubah objek menjadi string sebelum dikirim, dan JSON.parse(...) mengembalikannya menjadi objek di sisi penerima. Wajib dibungkus try-catch karena parse bisa gagal saat menerima data rusak.

Menangani JSON Rusak

Data dari jaringan tidak bisa dipercaya. Satu karakter salah bisa membuat seluruh aplikasi crash.

JSParse aman dengan try-catch
ws.on("message", (data) => {
  try {
    const pesan = JSON.parse(data.toString());
    prosesPesan(pesan);
  } catch {
    ws.send(JSON.stringify({ error: "format pesan tidak valid" }));
  }
});

Pola try-catch di atas mencegah satu pesan rusak mematikan proses server. Kirim respons error agar klien bisa memperbaiki diri, lalu lanjut memproses pesan berikutnya.

Pesan Binary

ArrayBuffer dan Blob

Untuk data seperti gambar, audio, atau file, binary jauh lebih efisien daripada teks. Browser memberikan dua representasi: ArrayBuffer dan Blob.

JSMenerima dan mengirim binary
ws.binaryType = "arraybuffer";
 
ws.onmessage = (event) => {
  if (typeof event.data === "string") {
    console.log("pesan teks:", event.data);
  } else {
    const buffer = new Uint8Array(event.data);
    console.log("pesan binary:", buffer.length, "byte");
  }
};
 
const bytes = new Uint8Array([1, 2, 3, 4]);
ws.send(bytes.buffer);

ws.binaryType = "arraybuffer" mengatur cara browser menyajikan data binary yang masuk. Pengiriman binary memakai ws.send(bytes.buffer) — ArrayBuffer atau Blob dikirim langsung tanpa serialisasi.

Kapan Memakai Binary

Binary hemat bandwidth dan lebih cepat diproses, tapi tidak bisa dibaca manusia. Aturan praktisnya: gunakan JSON untuk metadata dan pesan kecil, binary untuk data yang besar atau sudah terstruktur sebagai byte.

Format Data Terstruktur

MessagePack dan Protobuf

Jika aplikasi membutuhkan ukuran payload minimal dan kecepatan tinggi, ada format binary terstruktur.

Install library serialization
bun add @msgpack/msgpack

MessagePack mengubah objek menjadi binary yang jauh lebih kecil dari JSON, sementara Protocol Buffers (protobuf) membutuhkan skema .proto dan menghasilkan encoding paling ringkas. Untuk aplikasi kecil, perbedaan ini jarang terasa; untuk jutaan pesan per hari, ia sangat berarti.

Kompresi per Pesan

Ekstensi permessage-deflate mengompresi pesan saat dikirim dan mendekompresi saat diterima, transparan untuk kalian sebagai developer.

JSAktifkan kompresi di server ws
const { WebSocketServer } = require("ws");
 
const wss = new WebSocketServer({
  port: 8080,
  perMessageDeflate: true,
});

perMessageDeflate: true mengaktifkan kompresi di server ws. Perhatikan trade-off: kompresi menambah latensi CPU dan memori, jadi untuk pesan kecil yang tidak berulang, mematikannya justru lebih cepat.

Pola Envelope

Struktur Pesan Seragam

Setiap pesan dibungkus dengan struktur tetap yang memuat tipe dan payload. Ini disebut envelope.

JSStruktur envelope
const envelope = {
  v: 2,
  type: "message:send",
  id: "msg_7f3a",
  data: {
    to: "user:12",
    teks: "Halo!",
  },
};

Field type menentukan bagaimana penerima memproses payload, id untuk tracking dan deduplikasi, dan v untuk versi protokol. Dengan envelope, kalian bisa menambah event baru tanpa memecah klien lama.

Versioning Pesan

Saat protokol berkembang, gunakan field versi untuk memigrasi klien secara bertahap.

JSHandle versi berbeda
function prosesEnvelope(envelope) {
  if (envelope.v !== 2) {
    return { error: "versi protokol tidak didukung" };
  }
  return prosesBerdasarkanTipe(envelope);
}

Cek versi di awal memungkinkan server menolak klien tua dengan pesan yang jelas, atau menjalankan transformasi untuk kompatibilitas mundur.

Penutup

Episode 10 membuat kalian sadar bahwa isi pesan WebSocket adalah keputusan desain, bukan sesuatu yang ditentukan protokol. JSON untuk kemudahan, binary untuk efisiensi, format terstruktur untuk skala besar, dan envelope untuk evolusi protokol.

Inti yang harus dibawa pulang:

  • JSON adalah format default yang paling mudah digunakan dan didebug.
  • Parse JSON selalu dibungkus try-catch karena data jaringan tidak bisa dipercaya.
  • Binary ArrayBuffer dan Blob efisien untuk file dan data besar.
  • MessagePack dan protobuf menghemat bandwidth pada skala besar.
  • Envelope dengan field tipe, id, dan versi membuat protokol mudah dirawat.

Di episode 11 berikutnya kita membahas presence & heartbeat mechanisms: ping-pong frame, deteksi koneksi mati, status online dan offline pengguna, serta pengaturan interval heartbeat di Socket.IO.

Belajar WebSocket - Message Serialization & Data Formats | Belajar WebSocket