Ketiga materi ini — GraphQL, Apache Thrift, dan Protocol Buffers (Protobuf) & gRPC — digabung dalam satu catatan karena merupakan sub-topik/varian teknologi konkret dari tema besar RPC (Remote Procedure Call) dan serialization pada aplikasi terdistribusi. Ketiganya menjawab masalah yang sama dari sudut berbeda: bagaimana client dan server saling bertukar data & memanggil fungsi secara efisien, lintas bahasa pemrograman, dan (untuk sebagian) lintas platform — sebagai alternatif dari REST API biasa.
GraphQL
Motivasi: Keterbatasan REST API (Query-based API)
REST API adalah style paling populer untuk API berbasis web, tapi tidak semua kebutuhan cocok dengan model REST. Dua masalah utama:
- Endpoint berbasis resource memerlukan beberapa pemanggilan API untuk mendapatkan data yang saling terkait (misal harus GET user, lalu GET posts user tsb, lalu GET comments tiap post — banyak round-trip).
- Tidak bisa memilih field spesifik yang ingin diambil (misal hanya ingin daftar nama siswa, tapi response tetap membawa seluruh field object siswa).
Query-based API hadir sebagai solusi: menyediakan mekanisme query dan spesifikasi respons yang lebih detail, mencakup:
- Pengambilan representasi resource lengkap berbasis id.
- Listing koleksi resource dengan pagination dan filtering.
- Mutasi data.
- Response shaping — menentukan field apa saja yang ingin diambil.
- Deep & shallow fetch — bisa mengambil data secara dangkal (hanya field induk) atau dalam (termasuk relasi/nested object).
Salah satu contoh Query-based API yang distandarisasi OASIS adalah OData (sering dikombinasikan dengan REST API untuk advanced query, contoh pemakaiannya di Microsoft Graph API untuk mengakses platform Office 365 — datanya sendiri berbentuk graph relasi antar entity seperti Organization, Groups, Files, Chat, User, dsb).

Contoh query OData: GET serviceRoot/Airports('KSFO')/Name hanya mengembalikan field Name dari resource tersebut, atau GET serviceRoot/People?$filter=FirstName eq 'Scott' untuk filtering koleksi. Microsoft Graph Explorer menyediakan tool interaktif untuk mencoba query semacam ini terhadap resource nyata (mis. GET https://graph.microsoft.com/v1.0/me).

Definisi GraphQL
GraphQL adalah RPC-based API yang menyediakan fitur query dan mutation data (https://graphql.org/). Dikembangkan secara internal di Facebook pada 2012, dan dirilis ke publik pada 2015.
GraphQL populer digunakan sebagai interface antara aplikasi web berbasis SPA (Single-Page Application) dan aplikasi mobile dengan backend datastore, karena mampu mengambil data dengan beragam granularitas dan mendukung deep nested graph structure — cocok untuk data yang kompleks dan saling berelasi (seperti relasi antar entity pada graph), bukan sekadar resource flat.
Filosofi utamanya adalah “ask for what you want, get exactly that” — client menyatakan secara eksplisit struktur data (field) yang ia butuhkan lewat query, dan server mengembalikan response dengan shape yang persis sama seperti bentuk query tersebut (response shaping). Ini menyelesaikan dua masalah REST di atas sekaligus: satu request bisa mengambil data yang dalam/nested (deep fetch) tanpa banyak round-trip, dan client bisa memilih field spesifik saja (shallow atau selektif) tanpa over-fetching maupun under-fetching.
Contoh Query & Response
Query sederhana mengambil field spesifik dari satu resource (employee) berdasarkan id:
{
employee(id: 42) {
name
email
birthDate
hireDate
}
}Response mengikuti shape yang sama persis dengan query:
{
"data": {
"employee": {
"id": 42,
"name": "Jane Doe",
"email": "jane@doe.name",
"birthDate": "01/01/1990",
"hireDate": "01/01/2020"
}
}
}Contoh deep fetch (nested graph, relasi satu-ke-banyak) — mengambil hero beserta daftar friends-nya sekaligus dalam satu request:
{
hero {
name
friends {
name
}
}
}{
"data": {
"hero": {
"name": "R2-D2",
"friends": [
{ "name": "Luke Skywalker" },
{ "name": "Han Solo" },
{ "name": "Leia Organa" }
]
}
}
}Komponen GraphQL
1. Data Schema — mendefinisikan tipe dan struktur data yang tersedia pada API, dipakai untuk validasi baik di sisi client maupun server (query yang menyebut field yang tidak ada di schema akan ditolak). Contoh schema (Star Wars API):
type Query {
human(id: ID!): Human
}
type Human {
name: String
appearsIn: [Episode]
starships: [Starship]
}
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
type Starship {
name: String
}2. Resolver — implementasi di sisi GraphQL server yang bertugas menjalankan (mengeksekusi) query. Setiap field pada setiap type di-backup oleh sebuah resolver yang diimplementasikan developer. Saat sebuah field pada query dieksekusi, resolver yang bersesuaian dengan field tersebut akan dijalankan — inilah yang menjembatani schema deklaratif dengan sumber data nyata (database, service lain, dsb).
Contoh resolver untuk field human pada Query (mengambil data dari database via context.db):
Query: {
human(obj, args, context, info) {
return context.db.loadHumanByID(args.id).then(
userData => new Human(userData)
)
}
}Resolver untuk field sederhana yang tinggal membaca properti object (name, appearsIn):
Human: {
name(obj, args, context, info) {
return obj.name
}
}
Human: {
appearsIn(obj) {
return obj.appearsIn
}
}Resolver untuk field relasi (starships) yang perlu memanggil sumber data lain untuk tiap id dalam list — inilah mekanisme di balik deep/nested fetch, tiap level nesting pada query akan memicu resolver-nya masing-masing secara berjenjang:
Human: {
starships(obj, args, context, info) {
return obj.starshipIDs.map(
id => context.db.loadStarshipByID(id).then(
shipData => new Starship(shipData)
)
)
}
}Hasil akhir ketika query menggabungkan field flat dan nested sekaligus:
{
human(id: 1002) {
name
appearsIn
starships {
name
}
}
}{
"data": {
"human": {
"name": "Han Solo",
"appearsIn": ["NEWHOPE", "EMPIRE", "JEDI"],
"starships": [
{ "name": "Millenium Falcon" },
{ "name": "Imperial shuttle" }
]
}
}
}Apache Thrift
Definisi & Motivasi
Apache Thrift adalah RPC-based software library yang dikembangkan di Facebook, dengan fokus pada:
- Scalability
- Efficient & reliable communication
- Multi-language (polyglot) — mendukung C++, Java, Python, PHP, C#, Erlang, JavaScript, Ruby, Objective-C, dan lain-lain.
Thrift menangani tiga hal utama: serialisasi, service definition, dan server threading. Elemen-elemen yang didefinisikan mencakup: namespace, tipe data, exceptions, dan services (kumpulan prosedur/fungsi yang disediakan untuk pemanggilan remote).
IDL (Interface Definition Language)
IDL menyediakan cara untuk menyatakan struktur data dan services secara language-independent (bebas bahasa). Dari satu file IDL, compiler Thrift (thrift --gen <bahasa>) dapat membangkitkan kode untuk berbagai bahasa target sekaligus (misal Python dan Java) dari sumber definisi yang sama:

Karakteristik inilah yang membuat Thrift memungkinkan cross-platform service — sebuah fungsi/module yang ditulis di satu bahasa (misal C++ sail stats module) bisa diakses dari aplikasi web berbasis Node.js melalui client stub dan server stub yang dibangkitkan dari IDL yang sama, menjadikan set fungsi tersebut sebuah network-based microservice yang bisa diakses dari berbagai platform dan bahasa.
Selain untuk RPC, tipe serialisasi Thrift juga dapat dipakai untuk serialisasi pesan pada messaging platform (NATS, RabbitMQ, AWS SQS, Apache Qpid, dll) agar program di platform/bahasa berbeda (mis. Python 32-bit Windows dan Java 64-bit RHEL) bisa saling bertukar data secara konsisten.
Type System
- Tipe dasar:
bool,byte,i16,i32,i64,double,string(UTF-8). - Tipe khusus:
binary. - Struct: mirip dengan struct pada bahasa C.
- Containers:
list<t>,set<t>,map<t1,t2>. - Exception: tipe khusus untuk penanganan error.
- Services: terdiri atas nama fungsi yang disediakan oleh server.
IDL Services
Services menyatakan prosedur/method yang dapat dipanggil secara remote, mirip dengan Java interface — signature-nya didefinisikan pada IDL, sementara implementasi method-nya ditulis pada bahasa target (Python, Java, dsb).
service CalculatorService
{
i32 add(1:i32 n1, 2:i32 n2)
}Positional Arguments & Evolvability
Perhatikan bahwa parameter fungsi Thrift diberi nomor eksplisit di depan tipe datanya (1:i32 n1, bukan sekadar i32 n1). Ini disebut positional arguments, dan tujuannya adalah agar service tetap evolvable (bisa berkembang tanpa merusak kompatibilitas).
Ilustrasi masalah: misalkan sebuah service awalnya void addUser(String firstname, string lastname, i32 ID), lalu suatu saat dikembangkan menjadi void addUser(String fullname, i32 ID, i32 phonenum) — argumen berubah urutan, ada yang dihapus (lastname), ada yang ditambah (phonenum). Informasi tipe saja tidak cukup untuk membedakan versi lama dan baru dari service ini secara aman; karena itu diperlukan nomor argumen/parameter eksplisit:
void addUser(1:string firstname, 2:string lastname, 3:i32 ID)
void addUser(4:string fullname, 3:i32 ID, 5:i32 phonenum)Dengan penomoran ini, field ID (nomor 3) tetap dikenali sebagai field yang sama meski posisi/nama parameter di sekitarnya berubah — inilah dasar mekanisme backward/forward compatibility Thrift.
Penomoran eksplisit yang sama juga berlaku pada struct, dilengkapi modifier required/optional (dan bisa diberi default value):
struct Location {
1: required double latitude;
2: required double longitude;
}
struct Tweet {
1: required i32 userId;
2: required string userName;
3: required string text;
4: required Location loc;
16: optional string language = "english"
}Arsitektur Thrift Framework: Protocol & Transport
Arsitektur Apache Thrift Framework memisahkan tanggung jawab menjadi beberapa lapisan (dari atas: Client program/Service handler → Service stubs → User types → Protocol → Transport → Device):
- Protocol: menyediakan serialisasi dari user types ke format serial (memetakan in-memory data structure ke on-the-wire format). Protocol tahu cara mengonversi tiap tipe data untuk tiap bahasa, misalnya lewat fungsi
writeI32(i32),readI32(i32),writeString(string),readString(string). - Transport: menangani pengiriman data dalam byte level — bisa lewat jaringan (TCP/HTTP), disk, maupun memory, dan bisa juga dipakai untuk fitur logging.

Secara lebih rinci pada arsitektur client-server, terdapat TProtocol (menangani format data yang dikirim antar client-server — text, biner, atau compress) dan TTransport (menangani mekanisme pengiriman data — socket, memory, atau file):

Varian Protocol
- BinaryProtocol — format biner straightforward, meng-encode nilai numerik sebagai binary (bukan dikonversi ke text).
- TCompactProtocol — encoding data yang sangat efisien dan padat (dense).
- TDenseProtocol — mirip TCompactProtocol tapi melepas meta information dari data yang dikirim dan menambahkannya kembali di sisi penerima (masih eksperimental, belum tersedia di implementasi Java).
- TJSONProtocol — menggunakan JSON untuk encoding data.
- TSimpleJSONProtocol — protocol JSON write-only, cocok untuk diparsing oleh scripting language.
- TDebugProtocol — menggunakan format text yang human-readable untuk membantu proses debugging.
Varian Transport
- TSocket — menggunakan blocking socket I/O untuk transport.
- TFramedTransport — mengirim data dalam bentuk frame, tiap frame didahului informasi panjang (length). Transport ini wajib dipakai saat menggunakan non-blocking server.
- TFileTransport — menulis ke file (tidak termasuk pada implementasi Java, tapi cukup sederhana untuk diimplementasikan sendiri).
- TMemoryTransport — menggunakan memory untuk I/O (implementasi Java memakai
ByteArrayOutputStreamsecara internal). - TZlibTransport — melakukan kompresi menggunakan zlib, dipakai bersamaan dengan transport lain (tidak tersedia di implementasi Java).
Processor & Server
Processor adalah “lem” (glue) hasil generate compiler yang menghubungkan pesan-pesan protokol RPC dengan kode yang ditulis developer.
Server berperan sebagai high-level controller yang: membuat transport (misal membuka TCP socket, bind, listen, accept), membuat input/output protocol, membuat processor berdasarkan protocol tersebut, lalu menunggu koneksi masuk dan menyerahkannya ke processor.
Thrift menyediakan beberapa pola server:
- TSimpleServer — single-threaded, blocking I/O. Berguna untuk keperluan testing.
- TThreadPoolServer — multi-threaded, blocking I/O.
- TNonblockingServer — multi-threaded, non-blocking I/O (implementasi Java memakai NIO channel). Harus menggunakan
TFramedTransport.
Model Pengembangan Aplikasi Thrift
Alur pengembangan aplikasi berbasis Thrift terdiri atas tiga langkah:
- Buat thrift file (definisi service, IDL).
- Implementasi handler dan server.
- Implementasi client.
Contoh definisi service pada file .thrift:
namespace java if4031
typedef i32 int
service CalculatorService
{
int multiply(1:int n1, 2:int n2),
int add(1:int n1, 2:int n2),
}Perintah pembangkitan kode: thrift --gen <bahasa> calculator.thrift, yang menghasilkan: kelas interface (Iface) service, kelas client dan Processor (untuk server), serta kelas yang merepresentasikan struktur/tipe data dan exception (jika ada).
Kode interface hasil generate (Java):
public class CalculatorService {
public interface Iface {
public int multiply(int n1, int n2) throws org.apache.thrift.TException;
public int add(int n1, int n2) throws org.apache.thrift.TException;
}Kode client hasil generate — tiap method dipecah menjadi send_xxx lalu recv_xxx:
public static class Client extends org.apache.thrift.TServiceClient implements Iface {
public int multiply(int n1, int n2) throws org.apache.thrift.TException {
send_multiply(n1, n2);
return recv_multiply();
}
public int add(int n1, int n2) throws org.apache.thrift.TException {
send_add(n1, n2);
return recv_add();
}Implementasi handler di sisi server — developer mengimplementasikan interface Iface hasil generate dengan logika bisnis sesungguhnya:
public class CalculatorHandler implements CalculatorService.Iface {
@Override
public int multiply(int n1, int n2) throws TException {
System.out.println("Multiply(" + n1 + "," + n2 + ")");
return n1 * n2;
}
...
}Program utama server (contoh sederhana dengan TSimpleServer):
CalculatorHandler handler = new CalculatorHandler();
CalculatorService.Processor processor = new CalculatorService.Processor(handler);
TServerTransport serverTransport = new TServerSocket(9090);
TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));
server.serve();Implementasi client — membuka transport, membungkusnya dengan protocol, lalu memanggil method service seolah-olah pemanggilan fungsi lokal biasa:
TTransport transport;
transport = new TSocket("localhost", 9090);
transport.open();
TProtocol protocol = new TBinaryProtocol(transport);
CalculatorService.Client client = new CalculatorService.Client(protocol);
int product = client.multiply(3,5);Performance
Perbandingan waktu penyelesaian 1 juta service request untuk berbagai kombinasi server Java menunjukkan Thrift jauh lebih cepat dibanding SOAP/REST berbasis HTTP+XML/JSON, dan makin cepat lagi bila memakai transport TCP langsung serta protocol Compact (bukan JSON):

Urutan performa dari yang paling lambat ke tercepat: SOAP (JAX-WS, Tomcat, HTTP, XML) → REST (JAX-RS/Jersey, Tomcat, HTTP, JSON) → Apache Thrift (Tomcat, HTTP, JSON) → Apache Thrift (TCP, JSON) → Apache Thrift (TCP, Compact) — yang tercepat.
Protocol Buffers (Protobuf) & gRPC
Definisi
Protocol Buffer (Protobuf) adalah sebuah data serialization library yang terdiri atas: description language (IDL), compiler, dan library runtime. Dikembangkan dan digunakan secara luas di Google, dengan fokus pada efisiensi, language interoperability, dan usability. Bahasa yang didukung secara official: C++, Java, dan Python (bahasa lain didukung lewat implementasi pihak ketiga/generator plugin).
gRPC adalah library multi-language untuk implementasi RPC yang dibangun di atas Protocol Buffer. Dibanding Apache Thrift, kombinasi Protobuf & gRPC bersifat lebih opinionated (lebih ketat aturannya) — misalnya secara default sudah menetapkan transport-nya menggunakan HTTP/2, sementara Thrift membebaskan pilihan transport (TCP, memory, file, dll).

Pola kerjanya: definisi service ditulis di file .proto (mis. ProductInfo.proto), lalu dari file ini di-generate client stub (dipakai oleh Consumer) dan server skeleton (dipakai oleh service Product Info), yang saling berkomunikasi lewat Protocol Buffer di atas HTTP/2 — dan ini bisa terjadi lintas bahasa (contoh pada diagram: consumer berbahasa Java, server berbahasa Go).
HTTP/2 sebagai Fondasi Transport
gRPC memanfaatkan HTTP/2 yang menambahkan binary framing layer dibanding HTTP/1.1 yang berbasis text. Pesan request/response HTTP/1.1 (headers + body dalam bentuk teks) dipecah menjadi HEADERS frame dan DATA frame dalam bentuk biner pada HTTP/2:

Keuntungan penting dari binary framing ini adalah kemampuan multiplexing — banyak stream (request/response) bisa berjalan bersamaan dalam satu koneksi TCP yang sama, tanpa harus saling menunggu (berbeda dari HTTP/1.1 yang rawan head-of-line blocking). Frame dari stream berbeda (stream 1, 3, 5, dst.) bisa saling berselang-seling pada satu koneksi yang sama antara client dan server:

Definisi Pesan (.proto) & Pembangkitan Kode
Struktur data pada Protobuf didefinisikan dalam file .proto menggunakan message, dengan tiap field memiliki nomor unik (mirip konsep positional numbering pada Thrift, untuk keperluan evolvability format biner) serta modifier required/optional/repeated:
package tutorial;
option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0; HOME = 1; WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook { repeated Person person = 1; }Kode untuk bahasa target dibangkitkan lewat compiler protoc:
protoc -I=<src> --java_out=<dst> $srcdir/tutorial.proto
Contoh pemakaian kelas hasil generate (Java, pola builder):
Person john =
Person.newBuilder()
.setId(1234)
.setName("John Doe")
.setEmail("jdoe@example.com")
.addPhone(
Person.PhoneNumber.newBuilder()
.setNumber("555-4321")
.setType(Person.PhoneType.HOME)
)
.build();Parsing & Serialization
Kelas message hasil generate menyediakan method standar untuk serialisasi/deserialisasi ke berbagai bentuk:
byte[] toByteArray();— mengserialisasi message menjadi array byte mentah.static Person parseFrom(byte[] data);— mem-parsing message dari array byte.void writeTo(OutputStream output);— mengserialisasi message dan menuliskannya keOutputStream.static Person parseFrom(InputStream input);— membaca dan mem-parsing message dariInputStream.
Contoh penggunaan langsung ke file:
FileOutputStream output = new FileOutputStream(args[0]);
addressBook.build().writeTo(output);
AddressBook addressBook = AddressBook.parseFrom(new FileInputStream(args[0]));RPC Support: gRPC
Selain untuk serialisasi data biasa, Protobuf juga menyediakan sintaks untuk mendefinisikan service RPC lewat gRPC (http://www.grpc.io/):
service HelloService {
rpc SayHello (HelloRequest) returns (HelloResponse);
}
message HelloRequest {
required string greeting = 1;
}
message HelloResponse {
required string reply = 1;
}gRPC mendukung empat jenis request/pola komunikasi, memanfaatkan kapabilitas streaming HTTP/2:
- Unary RPC — satu request menghasilkan satu response tunggal.
rpc SayHello(HelloRequest) returns (HelloResponse){ } - Server streaming RPC — satu request menghasilkan stream of response.
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){ } - Client streaming RPC — stream request menghasilkan satu response tunggal.
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) { } - Bidirectional streaming RPC — stream request menghasilkan stream response (dua arah).
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){ }
Dukungan bidirectional streaming secara native inilah salah satu keunggulan gRPC dibanding Thrift.
gRPC membangkitkan stub client dan server-side code dari definisi .proto; developer tinggal menulis kode untuk memanggil client stub tersebut, dan mengimplementasikan API call yang sesungguhnya di sisi server.
Alur Kerja gRPC + Protobuf di atas HTTP/2
Contoh definisi service ProductInfo dengan dua RPC method (addProduct, getProduct) beserta message Product dan ProductID:

Alur lengkap sebuah remote procedure call melalui jaringan (contoh getProduct("ABC")):
- Client memanggil prosedur
getProduct("ABC")secara lokal. - Stub di sisi client membangun encoded message (pesan biner terserialisasi) beserta message headers (
:method POST,:path /ProductInfo/getProduct). - Message dikirim melintasi jaringan lewat koneksi HTTP/2.
- Server machine menerima dan menyerahkan pesan tersebut ke server stub.
- Server stub unpack (decode) pesan tersebut menjadi request details (nama service, nama fungsi, value parameter).
- Server stub melakukan local call ke fungsi
getProductyang sesungguhnya (implementasi developer).
Kelebihan, Kekurangan & Perbandingan dengan Thrift
Perbandingan gRPC vs Thrift:
- gRPC menggunakan HTTP/2 sebagai transport, sedangkan Thrift menyediakan transport layer yang extensible (bisa TCP, memory, disk, AMQP, HTTP/2, websocket, dst).
- gRPC native mendukung bidirectional streaming; Thrift tidak menyediakan ini secara built-in.
- Secara popularitas, gRPC saat ini lebih populer dibanding Thrift.
- Dari sisi benchmark performa (rpc_benchmark, github.com/chrislee87/rpc_benchmark): untuk koneksi panjang (long connection), tidak ada perbedaan besar pada QPS — gRPC lebih unggul di latency lebih rendah, sementara Thrift lebih unggul di CPU usage lebih rendah. Untuk koneksi pendek (short connection), Thrift (TCP) justru mengungguli gRPC (HTTP/2) dalam hal QPS/CPU/latency. Catatan tambahan: pola kerja satu goroutine per koneksi membuat CPU usage meningkat signifikan seiring bertambahnya koneksi (sehingga pembatasan jumlah koneksi penting), dan latency untuk sebagian kecil koneksi bisa sulit dikontrol akibat Garbage Collector Go yang bersifat stop-the-world — untuk aplikasi real-time dengan requirement latency sangat ketat, disarankan memakai implementasi versi C/C++.
Perbandingan fitur bahasa (Thrift vs Protocol Buffers):
| Aspek | Thrift | Protocol Buffers |
|---|---|---|
| Composite Type | Struct {} | Message {} |
| Base Types | bool, byte, 16/32/64-bit integer, double, string | bool, 32/64-bit integer, float, double, string, byte sequence |
| Containers | list<t1>, set<t1>, map<t1,t2> | Tidak ada tipe container bawaan |
| Enumerations | Ya | Ya |
| Constants | Ya (mis. const i32 INT_CONST = 1234;) | Tidak |
| Exception Type/Handling | Ya (keyword exception, bukan struct) | Tidak |
Dari perbandingan ini terlihat bahwa Thrift memiliki type system yang lebih kaya (container bawaan, constant, exception type eksplisit), sementara Protobuf lebih ramping namun diimbangi ekosistem gRPC yang matang (HTTP/2, streaming) serta dukungan tooling Google yang luas. Kekurangan umum yang dirasakan pada Protobuf/gRPC: setup awal yang lebih hassle (harus mendefinisikan .proto, generate kode, mengatur toolchain protoc) dan hasil serialisasi tidak human-readable (format biner murni) — namun trade-off ini memberi keuntungan berupa payload yang sangat compact dan kecepatan serialisasi/deserialisasi yang tinggi, cocok untuk komunikasi RPC berperforma tinggi antar microservice.
Perbandingan Ringkas: GraphQL vs Thrift vs Protobuf/gRPC vs REST
| Aspek | REST (biasa) | GraphQL | Apache Thrift | Protobuf & gRPC |
|---|---|---|---|---|
| Format data | Umumnya JSON/XML via HTTP | JSON (request berupa query text, response JSON) | Biner (Binary/Compact), atau JSON (TJSONProtocol) | Biner (Protocol Buffer) di atas HTTP/2 |
| Human-readable | Ya (JSON/XML) | Ya (query & response berbasis text/JSON) | Tergantung protocol — bisa human-readable (TJSONProtocol, TDebugProtocol) atau tidak (Binary/Compact) | Tidak (payload biner murni) |
| Fleksibilitas pengambilan data | Rendah — endpoint tetap per resource, rawan over-/under-fetching | Tinggi — client tentukan field & kedalaman lewat query (deep/shallow fetch) | Rendah — signature fungsi tetap, ditentukan oleh IDL | Rendah — signature fungsi tetap, ditentukan oleh .proto |
| Performa | Relatif lambat (text-based, banyak round-trip untuk data relasional) | Baik untuk mengurangi jumlah round-trip; overhead parsing query | Tinggi, terutama dengan TCP + Compact protocol | Tinggi, payload sangat compact & cepat di-serialize |
| Cross-language / polyglot | Ya (berbasis HTTP standar) | Ya (berbasis HTTP standar) | Ya — didesain khusus polyglot lewat IDL (C++, Java, Python, PHP, C#, Erlang, JS, Ruby, Obj-C, dll) | Ya — official C++/Java/Python, plus dukungan luas lewat gRPC di banyak bahasa |
| Use case umum | Public web API, kebutuhan sederhana/CRUD | Backend untuk SPA/mobile dengan data kompleks & nested (graph-like) | Komunikasi antar microservice performa tinggi dengan banyak bahasa berbeda | Komunikasi RPC internal berperforma sangat tinggi (mis. Google-scale microservice), termasuk streaming dua arah |
| Learning curve | Rendah — konsep resource & HTTP verb sudah umum | Sedang — perlu memahami schema, resolver, query language baru | Sedang-tinggi — perlu memahami IDL, protocol & transport layer, code generation | Sedang-tinggi — perlu memahami .proto, toolchain protoc, konsep HTTP/2 & streaming gRPC |
Flashcard
flashcards Apa masalah utama REST API yang coba diselesaikan oleh Query-based API seperti GraphQL? :: (1) Endpoint berbasis resource memerlukan beberapa pemanggilan API untuk mendapatkan data yang saling terkait; (2) Tidak bisa memilih field spesifik yang ingin diambil (rawan over-fetching/under-fetching). Apa itu resolver pada GraphQL dan kapan ia dijalankan? :: Resolver adalah implementasi di sisi GraphQL server untuk menjalankan query — setiap field pada setiap type di-backup oleh resolver, dan saat field tersebut dieksekusi pada query, resolver yang bersesuaian akan dijalankan (termasuk untuk field relasi/nested, memicu resolver berjenjang). Kapan dan di mana Apache Thrift dikembangkan, dan apa tiga hal utama yang ditanganinya? :: Dikembangkan di Facebook; menangani serialisasi, service definition, dan server threading, dengan fokus pada scalability, efficient & reliable communication, dan dukungan multi-language (polyglot). Mengapa Thrift menggunakan positional/explicit numbering pada parameter dan field struct? :: Agar service tetap evolvable — ketika parameter ditambah/dihapus/diganti nama seiring waktu, informasi tipe saja tidak cukup untuk membedakan versi lama dan baru; nomor field eksplisit memastikan field yang sama tetap dikenali meski urutan/nama berubah. Sebutkan perbedaan peran TProtocol dan TTransport pada arsitektur Apache Thrift. :: TProtocol menangani format data yang dikirim antar client-server (text, biner, atau compress), sedangkan TTransport menangani mekanisme pengiriman data secara byte-level (socket, memory, atau file). Apa itu Protocol Buffer (Protobuf) dan apa hubungannya dengan gRPC? :: Protobuf adalah data serialization library (terdiri atas IDL, compiler, dan library) yang dikembangkan Google, fokus pada efisiensi dan language interoperability; gRPC adalah library multi-language untuk implementasi RPC yang dibangun di atas Protocol Buffer, secara default menggunakan transport HTTP/2. Sebutkan 4 jenis request/pola komunikasi yang didukung gRPC. :: Unary RPC (single request-single response), Server streaming RPC (single request-stream response), Client streaming RPC (stream request-single response), dan Bidirectional streaming RPC (stream request-stream response). Apa perbedaan utama gRPC dan Thrift dari sisi transport dan streaming? :: gRPC menggunakan HTTP/2 sebagai transport dan secara native mendukung bidirectional streaming; Thrift menyediakan transport layer yang extensible (TCP, memory, disk, AMQP, HTTP/2, websocket) tapi tidak punya dukungan bidirectional streaming bawaan. Apa kelebihan dan kekurangan utama Protobuf/gRPC dibanding format berbasis text seperti JSON/REST? :: Kelebihan: payload sangat compact dan kecepatan serialisasi/deserialisasi tinggi (cocok untuk RPC performa tinggi). Kekurangan: setup awal lebih hassle (perlu mendefinisikan .proto dan generate kode lewat protoc) dan hasil serialisasi tidak human-readable karena berupa biner murni.