Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
20 Aug 2025 · 6 mnt baca ·Artikel 73 / 110
Go

73. gRPC-Web untuk Komunikasi dengan Frontend (React/Vue)

IH
Ihsan Arif
Penulis di Santekno · Backend Engineer

73. gRPC-Web untuk Komunikasi dengan Frontend (React/Vue)

Di era modern aplikasi web, kebutuhan akan komunikasi efisien dan reaktif antara frontend dan backend semakin penting. Tradisionalnya, API berbasis REST menggunakan JSON menjadi pilihan utama. Namun, kini mulai banyak engineering team yang melirik gRPC sebagai alternatif dengan latensi rendah dan efisiensi tinggi berkat Protobuf. Meski demikian, gRPC pada dasarnya berjalan di atas HTTP/2—yang tidak didukung semua browser secara native untuk gRPC. Di sinilah gRPC-Web hadir sebagai jembatan teknologi untuk memungkinkan browser (React/Vue) berkomunikasi dengan backend gRPC.

Pada tulisan ini, saya akan membahas konsep gRPC-Web, cara konfigurasinya, dan contoh implementasi pada frontend React/Vue yang berinteraksi dengan backend gRPC. Mari kita mulai dengan pengenalan singkat.


Apa itu gRPC dan gRPC-Web?

gRPC Secara Singkat

gRPC adalah remote procedure call framework berbasis HTTP/2 yang dikembangkan oleh Google. Ia memakai Protocol Buffers (“Protobuf”) sebagai format serialisasi data yang lebih kompak dan cepat dibanding JSON. gRPC terkenal dengan fitur Contract First, Multi-language (Polyglot), dan streaming (bidirectional dan server/client streaming).

Kendala gRPC di Browser

Sayangnya, browser saat ini tidak mendukung sepenuhnya fitur yang dibutuhkan oleh protokol gRPC, terutama untuk HTTP/2 framing dan header. Paket gRPC yang tersedia untuk Node.js pun tidak bisa di-bundle ke dalam browser. Di sinilah gRPC-Web menjadi solusi.

gRPC-Web: Jembatan untuk Browser

gRPC-Web adalah proyek yang memungkinkan aplikasi web (React, Vue, Angular, dsb.) memanggil API gRPC backend. Ia menyediakan library JavaScript dan protokol wire sederhana di atas HTTP/1.1/2 dengan CORS, sehingga aplikasi frontend bisa berkomunikasi dengan backend gRPC.


Arsitektur gRPC-Web

Mari visualisasikan arsitekturnya:

MERMAID
flowchart LR
    A[React/Vue SPA
gRPC-Web Client] --protokol gRPC-Web--> B[gRPC-Web Proxy] B --gRPC--> C[gRPC Backend Service]
  • React/Vue SPA: Browser menggunakan gRPC-Web client untuk membuat request.
  • gRPC-Web Proxy: Tools seperti Envoy atau standalone proxy menerjemahkan request HTTP/1.1 gRPC-Web menjadi HTTP/2 gRPC untuk forward ke backend gRPC.
  • gRPC Backend Service: Microservice/Backend menjalankan server gRPC.

Studi Kasus Sederhana: Todo Service

1. Definisikan Protobuf

Misal kita ingin membuat aplikasi Todo sederhana. Berikut file todo.proto:

proto
 1syntax = "proto3";
 2
 3package todo;
 4
 5service TodoService {
 6  rpc ListTodos (Empty) returns (TodoListResponse);
 7  rpc AddTodo (AddTodoRequest) returns (TodoResponse);
 8}
 9
10message Empty {}
11
12message AddTodoRequest {
13  string title = 1;
14}
15
16message Todo {
17  int32 id = 1;
18  string title = 2;
19  bool completed = 3;
20}
21
22message TodoResponse {
23  Todo todo = 1;
24}
25
26message TodoListResponse {
27  repeated Todo todos = 1;
28}

2. Generate Stubs

Gunakan plugin protoc-gen-grpc-web untuk menghasilkan stub JS/TS:

bash
1protoc -I=./proto todo.proto \
2    --js_out=import_style=commonjs:./frontend/src/proto \
3    --grpc-web_out=import_style=typescript,mode=grpcwebtext:./frontend/src/proto

3. Setup Backend gRPC

Misal kita implementasi backend di NodeJS (atau Go). Intinya backend ini menjalankan service TodoService di port tertentu (misal 50051). Di tulisan ini kita fokus pada bridging ke frontend.

4. Deploy gRPC-Web Proxy

Menggunakan Envoy (cara paling umum):

Config snippet envoy.yaml:

yaml
 1static_resources:
 2  listeners:
 3    - name: listener_0
 4      address:
 5        socket_address: { address: 0.0.0.0, port_value: 8080 }
 6      filter_chains:
 7        - filters:
 8            - name: envoy.filters.network.http_connection_manager
 9              typed_config:
10                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
11                codec_type: AUTO
12                stat_prefix: ingress_http
13                route_config:
14                  name: local_route
15                  virtual_hosts:
16                    - name: backend
17                      domains: ["*"]
18                      routes:
19                        - match: { prefix: "/" }
20                          route: { cluster: grpc_backend }
21                http_filters:
22                  - name: envoy.filters.http.grpc_web
23                  - name: envoy.filters.http.cors
24                  - name: envoy.filters.http.router
25  clusters:
26    - name: grpc_backend
27      connect_timeout: 0.25s
28      type: logical_dns
29      http2_protocol_options: {}
30      lb_policy: round_robin
31      load_assignment:
32        cluster_name: grpc_backend
33        endpoints:
34          - lb_endpoints:
35              - endpoint:
36                  address:
37                    socket_address:
38                      address: host.docker.internal
39                      port_value: 50051
Penjelasan: Envoy menerima request dari frontend di port 8080, meneruskannya ke backend gRPC di port 50051.


Implementasi di Frontend

React: Contoh Client

  1. Install Dependencies

    bash
    1npm install grpc-web google-protobuf

  2. Implementasi Todo Client

src/App.tsx:

tsx
 1import React, { useEffect, useState } from 'react';
 2import { TodoServiceClient } from './proto/todo_grpc_web_pb';
 3import { Empty, AddTodoRequest, Todo } from './proto/todo_pb';
 4
 5const client = new TodoServiceClient('http://localhost:8080', null, null);
 6
 7function App() {
 8  const [todos, setTodos] = useState<Todo.AsObject[]>([]);
 9  const [title, setTitle] = useState('');
10
11  useEffect(() => {
12    const req = new Empty();
13    client.listTodos(req, {}, (err, response) => {
14      if (response) setTodos(response.getTodosList().map(todo => todo.toObject()));
15    });
16  }, []);
17
18  const handleAdd = () => {
19    const req = new AddTodoRequest();
20    req.setTitle(title);
21    client.addTodo(req, {}, (err, response) => {
22      if (response) setTodos(old => [...old, response.getTodo()?.toObject()]);
23      setTitle('');
24    });
25  };
26
27  return (
28    <div>
29      <h1>Todo List (gRPC-Web)</h1>
30      <ul>
31        {todos.map(todo => (
32          <li key={todo.id}>
33            {todo.title} {todo.completed ? "✔" : ""}
34          </li>
35        ))}
36      </ul>
37      <input value={title} onChange={e => setTitle(e.target.value)} />
38      <button onClick={handleAdd}>Add Todo</button>
39    </div>
40  );
41}
42
43export default App;

Vue: Konsep yang Sama

  1. Install Dependency

    bash
    1npm install grpc-web google-protobuf

  2. Implementasi di Vue

src/components/Todo.vue:

vue
 1<template>
 2  <div>
 3    <h1>Todo List (gRPC-Web)</h1>
 4    <ul>
 5      <li v-for="todo in todos" :key="todo.id">{{ todo.title }} {{ todo.completed ? "✔" : "" }}</li>
 6    </ul>
 7    <input v-model="title" />
 8    <button @click="addTodo">Add Todo</button>
 9  </div>
10</template>
11
12<script lang="ts">
13import { defineComponent, ref, onMounted } from 'vue';
14import { TodoServiceClient } from '../proto/todo_grpc_web_pb';
15import { Empty, AddTodoRequest, Todo } from '../proto/todo_pb';
16
17const client = new TodoServiceClient('http://localhost:8080', null, null);
18
19export default defineComponent({
20  setup() {
21    const todos = ref<Todo.AsObject[]>([]);
22    const title = ref('');
23
24    onMounted(() => {
25      const req = new Empty();
26      client.listTodos(req, {}, (err, response) => {
27        if (response) todos.value = response.getTodosList().map(t => t.toObject());
28      });
29    });
30
31    const addTodo = () => {
32      const req = new AddTodoRequest();
33      req.setTitle(title.value);
34      client.addTodo(req, {}, (err, response) => {
35        if (response) todos.value.push(response.getTodo()?.toObject());
36        title.value = '';
37      });
38    };
39
40    return { todos, title, addTodo };
41  }
42});
43</script>

Bagaimana Performa Dibanding REST?

AspekREST (JSON)gRPC-Web (Protobuf)
Ukuran PayloadCenderung besar (teks)Lebih kecil (biner)
Seri/deserialisasiLambat (JSON.parse)Cepat (Protobuf)
Auto-doc/Type-safetyOptional via Swagger/OpenAPIBuilt-in via Proto
StreamingRumit (Server Sent Events)Native di gRPC/terbatas di Web*
Browser SupportUniversalButuh Proxy (gRPC-Web)
CORS/CredentialBuilt-inPerlu config di proxy

* Catatan: gRPC-Web hanya mendukung unary dan server streaming, client streaming belum didukung.


Kesimpulan: Apakah gRPC-Web Untuk Anda?

gRPC-Web membuka potensi penggunaan gRPC dalam stack frontend modern (React/Vue). Namun, ada trade-off:

Kelebihan:

  • Payload kecil, transmisi cepat.
  • Type-safety otomatis (dari Protobuf ke TypeScript/JS).
  • Mudah diintegrasikan multi-platform.

Kekurangan:

  • Setup dan debugging lebih kompleks (perlu Envoy/Proxy).
  • Streaming belum sepenuhnya didukung (non-bidirectional).
  • Tooling problem: DevTools dan error handling tidak sejelas fetch/AJAX biasa.

Jadi, jika Anda membutuhkan perfoma API tinggi, type-safe, dan punya tim yang terbiasa dengan Protobuf/gRPC, gRPC-Web layak dijajal dalam aplikasi React maupun Vue Anda.


Referensi

Selamat mencoba dan jangan lupa explore! Tuliskan pengalaman Anda menggunakan gRPC-Web di project frontend berikutnya di kolom komentar :)

Artikel Terkait

💬 Komentar