- JSON, yang telah menjadi standar untuk web API, mudah dibaca dan fleksibel, tetapi memiliki keterbatasan dalam hal performa dan stabilitas
- Protobuf (Protocol Buffers) menjamin struktur data secara jelas melalui definisi tipe yang ketat dan pembuatan kode otomatis
- Dengan menggunakan serialisasi biner, Protobuf dapat mengurangi ukuran data lebih dari sekitar 3x dan meningkatkan kecepatan transmisi dibanding JSON
- Server dan klien berbagi skema
.protoyang sama sehingga tidak ada ketidakcocokan tipe atau kebutuhan validasi manual - Walau lebih sulit untuk di-debug, Protobuf lebih cocok untuk API modern dari sisi performa, maintainability, dan efisiensi pengembangan
Universalitas dan Keterbatasan JSON
- JSON adalah format teks yang mudah dibaca manusia, sehingga data bisa diperiksa hanya dengan
console.log()sederhana - Berkat integrasi sempurna dengan web, JSON diadopsi luas di JavaScript dan berbagai framework backend
- JSON menawarkan fleksibilitas untuk menambah, menghapus, atau mengubah tipe field dengan bebas, tetapi hal ini juga membuka kemungkinan ketidakcocokan struktur dan error
- Karena ekosistem tooling-nya kaya, JSON bisa ditangani dengan mudah hanya menggunakan editor teks atau
curl - Namun, terlepas dari keunggulan tersebut, ada alternatif yang lebih baik dalam hal performa dan type safety
Gambaran Umum Protobuf
- Format serialisasi biner yang dikembangkan oleh Google pada 2001 dan dipublikasikan pada 2008
- Digunakan secara luas di sistem internal dan komunikasi antar-microservice
- Sering ada kesalahpahaman bahwa Protobuf harus dipakai bersama gRPC, padahal Protobuf juga bisa digunakan secara mandiri di HTTP API
- Pada awalnya kurang mudah diakses karena format biner tidak terlihat langsung, tetapi Protobuf sangat unggul dari sisi efisiensi dan stabilitas
Sistem Tipe yang Kuat dan Pembuatan Kode
- Protobuf mendefinisikan struktur data secara jelas melalui file
.proto- Setiap field memiliki tipe ketat, identifier numerik, dan nama tetap
- Contoh:
message User { int32 id = 1; string name = 2; string email = 3; bool isActive = 4; } - Dengan perintah
protoc, Protobuf mendukung pembuatan kode otomatis untuk banyak bahasa seperti Dart, TypeScript, Kotlin, Swift, C#, Go, dan Rust - Kode yang dihasilkan digunakan untuk serialisasi (
writeToBuffer) dan deserialisasi (fromBuffer), sehingga validasi atau parsing manual tidak diperlukan - Hasilnya, menghemat waktu sekaligus meningkatkan maintainability
Efisiensi Serialisasi Biner
- Protobuf diserialisasi sebagai data biner alih-alih teks, sehingga sangat ringkas dan cepat
- Perbandingan ukuran untuk data yang sama (objek
User):- JSON: 86 byte (68 byte jika spasi dihapus)
- Protobuf: 30 byte
- Penyebab efisiensinya:
- Menggunakan encoding varint untuk angka
- Menggunakan tag numerik, bukan key teks
- Menghapus spasi dan sintaks yang tidak perlu
- Optimasi field opsional
- Hasilnya adalah penghematan bandwidth, respon lebih cepat, hemat data seluler, dan peningkatan pengalaman pengguna
Contoh API Protobuf Berbasis Dart
- Menggunakan paket
shelfuntuk membuat HTTP server sederhana yang mengembalikan objekUserdalam format Protobuf - Inti kode server:
- Membuat objek
User()lalu menserialisasikannya denganwriteToBuffer() - Menetapkan header respons
'content-type': 'application/protobuf'
- Membuat objek
- Klien menggunakan paket
httpdanuser.pb.dartuntuk mendekode data Protobuf secara langsung - Karena server dan klien berbagi skema
.protoyang sama, ketidakcocokan struktur data tidak terjadi - Pendekatan yang sama juga dapat diterapkan di Go, Rust, Kotlin, Swift, C#, dan TypeScript
Keunggulan JSON yang Masih Tersisa
- Protobuf sulit dipahami maknanya tanpa skema
- Karena yang terlihat hanya identifier angka, bukan nama field, format ini sulit dibaca manusia
- Contoh perbandingan:
- JSON:
{ "id": 42, "name": "Alice" } - Protobuf:
1: 42, 2: "Alice"
- JSON:
- Karena itu, Protobuf memerlukan:
- tool decoding khusus
- manajemen skema dan versioning yang wajib
- Meski begitu, keuntungan performa dan efisiensinya jauh lebih besar
Kesimpulan
- Protobuf adalah teknologi serialisasi yang matang dan berperforma tinggi, serta cukup layak digunakan juga untuk API publik
- Dapat berjalan mandiri di HTTP API biasa tanpa gRPC
- Alat yang meningkatkan performa, robustness, pengurangan error, dan efisiensi pengembangan sekaligus
- Untuk proyek generasi berikutnya, mengadopsi Protobuf sangat layak dipertimbangkan
10 komentar
TypeSpec
https://typespec.io/
https://msgpack.org/ bagaimana dengan yang ini?
MessagePack juga bagus.
Saya rasa kontradiktif untuk mengklaim format yang bahkan tidak memiliki decoder resmi untuk debugging sebagai sesuatu yang matang.
Seperti semua alat lainnya, tidak ada yang serba bisa, tetapi saya rasa Protobuf juga merupakan alat yang cukup baik.
Khususnya ketika pernah ada kebutuhan untuk mengirimkan data berkapasitas besar dan berfrekuensi tinggi (20 kali per detik) ke berbagai bahasa [klien] di lingkungan embedded, saya pernah menanganinya dengan rapi menggunakan nanopb.
Kalau dibuat seketat itu, bukannya malah jadi pakai XML ya? haha
Skema juga bisa didefinisikan dengan DTD, dan jika di sisi parser di-cache, efeknya skema hanya perlu dikirim sekali.
=> Bukankah bagaimanapun juga skema memang harus dikirim setidaknya sekali? Bahkan pada JSON pun bukan berarti tidak ada skema; skemanya hanya tersirat dan ikut terkandung di dalam data, jadi rasanya bukan berarti skema tidak dikirim. Malah, karena skema yang sama dikirim berulang pada setiap item, itu justru lebih tidak efisien. "Berbasis skema tetapi juga menyertakan skema di dalam pesan" terdengar seperti ide yang cukup bagus.
Komentar Hacker News
JSON sering kali membuat kita mengirim data yang ambigu atau tidak terjamin. Berbagai masalah bisa muncul, seperti field yang hilang, kesalahan tipe, typo pada key, atau struktur yang tidak terdokumentasi. Ada tulisan yang berargumen bahwa Protobuf membuat hal-hal ini mustahil terjadi dengan mendefinisikan struktur pesan secara jelas lewat file
.proto. Namun ini adalah salah paham terhadap filosofi Protobuf. Diproto3, field required memang tidak didukung. Dokumentasi resmi (Protobuf Best Practices) juga secara eksplisit menyatakan bahwa “required fields are harmful and were removed”. Pada akhirnya, klien Protobuf juga harus ditulis secara defensif seperti API JSONjson:"-". Proyek saya bisa dilihat di GooeyJSON yang dikompresi sudah cukup layak dipakai, dan biaya komunikasi awalnya rendah. Tentu akan jadi masalah jika ada field yang hilang atau tipe berubah, tetapi kebanyakan orang yang mencoba merancang struktur yang sepenuhnya typed dan membuat proses sinkronisasi versi biasanya gagal. Pada akhirnya, opsi dengan biaya manusia yang lebih rendah akan menang. Karena itu, JSON tidak akan hilang sampai ada pengganti dengan biaya komunikasi antarmanusia yang lebih rendah
console.log()Protobuf tidak sempurna. Jika server dan klien dirilis pada waktu berbeda sehingga versi spesifikasinya berbeda, jaminan keamanannya runtuh. Ini bisa dikurangi dengan larangan reuse ID, penyalinan unknown-field, dan sebagainya, tetapi sistem terdistribusi pada dasarnya memang kompleks. Meski begitu,
protobuf3telah menyelesaikan banyak masalah diprotobuf2. Dulu kita tidak bisa membedakan apakah nilai default memang disetel atau field-nya hilang, tetapi sekarang ini bisa diatasi dengan memakai tipemessageDalam tulisan itu disebut “super efisien”, tetapi tidak ada pembahasan tentang gzip. Kebanyakan data teks sekarang sudah ditransmisikan dalam keadaan terkompresi secara otomatis. Karena itu, Protobuf seharusnya dibandingkan dengan JSON yang sudah digzip
Tidak masalah mendukung protokol yang lebih baik, tetapi sulit mengatakan bahwa Protobuf menggantikan JSON baik dalam efisiensi maupun kegunaan. Protobuf justru kehilangan area yang dikuasai JSON karena skemanya ketat. Sebaliknya, CBOR lebih cocok sebagai pengganti JSON. CBOR tetap fleksibel seperti JSON, tetapi memakai encoding yang lebih ringkas
ASN.1 dari tahun 1984 sebenarnya sudah melakukan apa yang dilakukan Protobuf, tetapi dengan lebih fleksibel. Jika memakai encoding DER, hasilnya juga tidak buruk. Lihat saja contoh ASN.1 DER. Protobuf terlalu kompleks dibanding apa yang berhasil dicapainya
Saya pernah membangun seluruh sistem produksi dengan Protobuf, dan pengelolaannya sendiri sangat menyakitkan. Secara teknis terlihat bagus, tetapi dalam praktiknya JSON jauh lebih sederhana
Protobuf memang hebat, tetapi sayang tidak mendukung zero-copy. Format seperti Cap’n Proto bisa menghilangkan bottleneck serialisasi/deserialisasi
Saya pernah membuat server untuk proyek NodeJS yang mendefinisikan seluruh API dengan
.proto, lalu merespons dengan proto atau JSON sesuai Content-Type. Ini jauh lebih terstruktur dibanding Swagger. Hanya saja, sangat disayangkan Google tidak menyediakan fungsi seperti ini dalam library resmi. gRPC juga merepotkan karena bergantung pada HTTP/2. Sebagai tambahan, menurut saya Text proto adalah bahasa konfigurasi statis terbaikFormat biner impian saya adalah yang berbasis skema tetapi juga menyertakan skema di dalam pesan. Dengan begitu, file-nya bisa langsung dibaca lewat plugin vim. Saat menangani jutaan objek, menempelkan skema 1KB ke pesan 2GB bukanlah beban besar
"Debugging memang sulit"
Lolos