Jika kamu sudah pernah membangun atau memakai REST API, kamu pasti akrab dengan pola request–response berbasis JSON lewat HTTP. Namun, saat aplikasimu harus berkomunikasi antar-service dengan sangat cepat dan terstruktur — misalnya di arsitektur microservices — JSON dan HTTP/1.1 mulai terasa lambat dan boros bandwidth. Di sinilah gRPC hadir: framework Remote Procedure Call (RPC) modern dari Google yang memakai Protocol Buffers (protobuf) sebagai format serialisasi biner dan HTTP/2 sebagai transport. Pada tutorial ini kamu akan belajar membangun service gRPC lengkap dengan Python, dari mendefinisikan skema hingga menguji server dan client.

Apa Itu gRPC dan Mengapa Menggunakannya?

gRPC adalah singkatan dari gRPC Remote Procedure Call. Dengan gRPC, client memanggil method pada server seolah-olah method itu adalah fungsi lokal, padahal sebenarnya dieksekusi di mesin lain. Ada tiga pilar utama yang membuat gRPC cepat dan efisien:

  • Protocol Buffers (protobuf) — format serialisasi biner yang ringkas dan punya skema terdefinisi.
  • HTTP/2 — mendukung multiplexing, kompresi header, dan komunikasi dua arah.
  • Kode di-generate otomatis — client stub dan server skeleton dibuat dari satu file .proto.

Apa bedanya dengan REST? REST umumnya memakai JSON lewat HTTP/1.1 dan berorientasi pada resource (URL), sedangkan gRPC memakai protobuf lewat HTTP/2 dan berorientasi pada method/fungsi. Keduanya punya tempat masing-masing — kita bandingkan lebih dalam di bagian akhir artikel ini.

Persiapan: Instalasi Dependensi

Kita hanya butuh dua paket: grpcio (runtime gRPC) dan grpcio-tools (untuk men-generate kode dari file .proto). Sebaiknya buat virtual environment terlebih dahulu agar dependensi tidak tercampur dengan proyek lain.

bash
python -m venv venv
source venv/bin/activate   # Windows: venv\Scripts\activate
pip install grpcio grpcio-tools

Kamu pengguna uv? Jalankan uv add grpcio grpcio-tools — instalasinya jauh lebih cepat dibanding pip.

Mendefinisikan Service dengan Protocol Buffers (.proto)

Semua service gRPC dimulai dari satu file .proto yang mendeskripsikan service (kumpulan method) dan message (struktur data). Kita akan membuat service Kalkulator dengan dua jenis RPC: unary (satu request → satu respons) dan server streaming (satu request → banyak respons).

other
syntax = "proto3";

package kalkulator;

// Service Kalkulator menyediakan operasi aritmatika sederhana.
service Kalkulator {
  // Unary RPC: satu permintaan -> satu respons.
  rpc Tambah (PermintaanTambah) returns (Hasil);

  // Server streaming RPC: satu permintaan -> banyak respons.
  rpc DeretFibonacci (PermintaanFibonacci) returns (stream Angka);
}

message PermintaanTambah {
  int32 a = 1;
  int32 b = 2;
}

message Hasil {
  int32 nilai = 1;
}

message PermintaanFibonacci {
  int32 jumlah = 1;
}

message Angka {
  int32 nilai = 1;
}

Angka 1, 2 di samping tipe data adalah field number — pengenal unik setiap field dalam skema protobuf. Kata kunci stream pada returns menandakan method tersebut mengirim banyak respons (server streaming).

Men-generate Kode Python dari File .proto

Jalankan perintah berikut untuk menghasilkan dua modul Python: kalkulator_pb2.py (definisi message) dan kalkulator_pb2_grpc.py (stub client dan skeleton server).

bash
python -m grpc_tools.protoc -I. \
    --python_out=. \
    --grpc_python_out=. \
    kalkulator.proto

Setelah dijalankan, dua file akan muncul di direktori kerjamu. Kamu tidak perlu mengedit file hasil generate ini — cukup impor keduanya di kode server dan client.

Membangun Server gRPC

Server gRPC mengimplementasikan method yang dideklarasikan di file .proto. Kita membuat class turunan dari KalkulatorServicer, lalu mendaftarkannya ke server. Simpan sebagai kalkulator_server.py:

python
from concurrent import futures

import grpc

import kalkulator_pb2
import kalkulator_pb2_grpc


class KalkulatorServicer(kalkulator_pb2_grpc.KalkulatorServicer):
    def Tambah(self, request, context):
        hasil = request.a + request.b
        print(f"[server] {request.a} + {request.b} = {hasil}")
        return kalkulator_pb2.Hasil(nilai=hasil)

    def DeretFibonacci(self, request, context):
        a, b = 0, 1
        for _ in range(request.jumlah):
            yield kalkulator_pb2.Angka(nilai=a)
            a, b = b, a + b


def serve():
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    kalkulator_pb2_grpc.add_KalkulatorServicer_to_server(KalkulatorServicer(), server)
    server.add_insecure_port("[::]:50051")
    server.start()
    print("Server gRPC berjalan di port 50051...")
    server.wait_for_termination()


if __name__ == "__main__":
    serve()

Method Tambah mengembalikan satu objek Hasil, sedangkan DeretFibonacci adalah generator — setiap yield mengirim satu respons ke client secara berurutan. Ini memanfaatkan generator Python untuk streaming tanpa memblokir thread.

Membangun Client gRPC

Di sisi client, kita membuat channel ke server lalu membungkusnya dengan KalkulatorStub. Simpan sebagai kalkulator_client.py:

python
import grpc

import kalkulator_pb2
import kalkulator_pb2_grpc


def run():
    with grpc.insecure_channel("localhost:50051") as channel:
        stub = kalkulator_pb2_grpc.KalkulatorStub(channel)

        # Unary RPC
        respon = stub.Tambah(kalkulator_pb2.PermintaanTambah(a=12, b=30))
        print(f"12 + 30 = {respon.nilai}")

        # Server streaming RPC
        print("10 angka Fibonacci pertama:")
        for angka in stub.DeretFibonacci(kalkulator_pb2.PermintaanFibonacci(jumlah=10)):
            print(angka.nilai, end=" ")
        print()


if __name__ == "__main__":
    run()

Perhatikan bahwa memanggil stub.Tambah(...) terasa seperti memanggil fungsi biasa, padahal eksekusinya terjadi di server. Untuk RPC streaming, hasil iterasi stub.DeretFibonacci(...) bisa langsung di-for seperti list biasa.

Menjalankan dan Menguji

Buka dua terminal. Di terminal pertama jalankan server, lalu di terminal kedua jalankan client.

bash
# Terminal 1 — server
python kalkulator_server.py
bash
# Terminal 2 — client
python kalkulator_client.py
other
# Output dari client
12 + 30 = 42
10 angka Fibonacci pertama:
0 1 1 2 3 5 8 13 21 34

gRPC vs REST: Kapan Memilih yang Mana?

gRPC dan REST API bukanlah pesaing mutlak — keduanya menjawab kebutuhan yang berbeda. gRPC unggul untuk komunikasi antar-service internal yang butuh kecepatan tinggi, kontrak tipe yang ketat, dan streaming dua arah. Sementara REST (misalnya lewat FastAPI) lebih mudah dipakai publik, ramah cache, dan bisa diakses langsung dari browser.

  • Format: gRPC memakai protobuf (biner), REST umumnya JSON (teks).
  • Transport: gRPC memakai HTTP/2, REST biasanya HTTP/1.1.
  • Kontrak API: gRPC punya skema .proto yang ketat; REST lebih longgar.
  • Browser: REST mudah dipanggil dari JavaScript, gRPC butuh gateway (misalnya gRPC-Web).

Contoh di tutorial ini memakai insecure_channel tanpa enkripsi TLS. Jangan gunakan itu di production — selalu amankan service gRPC dengan TLS/SSL atau mutual authentication (mTLS).

Versi Async dengan grpc.aio

Butuh performa I/O yang lebih tinggi? gRPC menyediakan varian asinkron lewat grpc.aio yang menyatu dengan event loop asyncio. Jika kamu belum familier dengan pemrograman asinkron di Python, baca dulu panduan lengkap asyncio kami. Berikut contoh server async minimal (hanya RPC Tambah):

python
import asyncio

import grpc.aio

import kalkulator_pb2
import kalkulator_pb2_grpc


class KalkulatorServicer(kalkulator_pb2_grpc.KalkulatorServicer):
    async def Tambah(self, request, context):
        return kalkulator_pb2.Hasil(nilai=request.a + request.b)


async def serve():
    server = grpc.aio.server()
    kalkulator_pb2_grpc.add_KalkulatorServicer_to_server(KalkulatorServicer(), server)
    server.add_insecure_port("[::]:50051")
    await server.start()
    print("Server gRPC async berjalan di port 50051...")
    await server.wait_for_termination()


if __name__ == "__main__":
    asyncio.run(serve())

Untuk RPC streaming versi async, cukup buat method async def yang menggunakan yield (async generator) — pola dasarnya sama persis dengan versi sinkron.

Kesimpulan

gRPC memberimu komunikasi antar-service yang cepat, terstruktur, dan ber-tipe kuat — andalan banyak arsitektur microservices modern. Dalam tutorial ini kamu sudah belajar mendefinisikan service dengan Protocol Buffers, men-generate kode, membangun server & client, hingga memahami perbedaan mendasar gRPC dan REST. Dari sini, kamu bisa mengeksplorasi streaming dua arah (bidirectional), autentikasi, dan integrasi dengan Kubernetes.

Apa perbedaan utama gRPC dan REST API?

gRPC memakai Protocol Buffers (biner) lewat HTTP/2 dan berorientasi pada method, sehingga lebih cepat dan ketat tipenya. REST umumnya memakai JSON lewat HTTP/1.1 dan berorientasi pada resource, sehingga lebih sederhana dan ramah browser.

Apakah gRPC bisa dipanggil langsung dari browser?

Belum secara native. Browser tidak bisa memakai HTTP/2 framing gRPC secara langsung. Solusinya adalah memakai gRPC-Web atau menambahkan gateway (seperti Envoy atau grpc-gateway) yang menerjemahkan HTTP/REST ke gRPC.

Apakah gRPC selalu lebih cepat daripada REST?

Untuk payload kecil dan panggilan antar-service internal, gRPC umumnya lebih cepat dan lebih hemat bandwidth karena protobuf biner dan multiplexing HTTP/2. Namun untuk API publik yang banyak di-cache atau diakses dari browser, REST tetap lebih praktis.