tutorial

Memahami Sintaks Dasar File Protobuf

Dalam dunia microservices dan komunikasi antar sistem yang modern, gRPC telah menjadi standar baru berkat efisiensi dan fleksibilitasnya. Namun, jantung dari gRPC bukanlah pada transport-nya saja, melainkan pada definisi pesan dan kontrak layanan yang ditulis dalam Protocol Buffers — atau yang biasa kita sebut file .proto.

Meski terlihat sederhana, file .proto menyimpan kekuatan besar. Ia adalah single source of truth antara berbagai sistem dan bahasa. Memahami sintaks dasar dari file ini adalah fondasi wajib bagi siapa pun yang ingin membangun sistem berbasis gRPC yang scalable dan maintainable.

Artikel ini akan mengajak kamu menyelami sintaks dasar file .proto — dari definisi message, tipe data, hingga service dan opsi tambahan.


1. Sintaks Dasar

Selalu Dimulai dengan syntax = “proto3”

syntax = "proto3";

Baris ini wajib ditulis di bagian atas file .proto. gRPC hanya mendukung Protobuf versi 3 (proto3). Versi ini memiliki banyak penyederhanaan dibanding versi sebelumnya (proto2), seperti tidak adanya keyword required dan optional (semua field dianggap optional secara default).


2. Package dan Namespace

package user;

option go_package = "github.com/santekno/grpc-user/api/userpb";
  • package: Menentukan namespace logis untuk file .proto. Ini berguna saat file dikompilasi ke beberapa bahasa agar tidak bentrok.
  • option go_package: Digunakan oleh plugin protoc-gen-go agar hasil generate masuk ke package Go yang diinginkan. Ini sangat penting untuk menjaga struktur modular dalam aplikasi.

3. Message: Struktur Data

message User {
  string id = 1;
  string name = 2;
  int32 age = 3;
  bool is_active = 4;
}

Sama seperti struct di Go atau class di OOP, message mendefinisikan data yang dikirimkan melalui gRPC. Setiap field memiliki:

  • Nama field (name)
  • Tipe data (string, int32, dll)
  • Nomor urut (= 1, = 2, dst) → tidak boleh diubah sembarangan!

Protobuf menggunakan nomor ini untuk serialisasi. Mengubah nomor field saat sistem sudah berjalan di produksi dapat menyebabkan kerusakan parsing di client/server.


4. Tipe Data yang Didukung Protobuf

Beberapa tipe data yang umum digunakan:

Proto3 TipePenjelasan
doubleFloating point 64-bit
floatFloating point 32-bit
int32Integer 32-bit
int64Integer 64-bit
stringUTF-8 string
boolBoolean
bytesRaw byte array
Kamu juga bisa menggunakan enum atau nested message untuk struktur yang lebih kompleks.


5. Enum: Untuk Nilai Tetap yang Terdefinisi

enum Status {
  UNKNOWN = 0;
  ACTIVE = 1;
  INACTIVE = 2;
}

gRPC dan Protobuf mendukung enum, yang sangat cocok untuk field seperti status, role, kategori, dan lainnya. Nilai pertama harus = 0, karena itu default untuk enum.


6. Service dan RPC: Inti dari gRPC

service UserService {
  rpc GetUser (GetUserRequest) returns (UserResponse);
  rpc CreateUser (CreateUserRequest) returns (UserResponse);
}
  • service: Seperti interface di Go, mendefinisikan metode yang tersedia.

  • rpc: Mendefinisikan satu prosedur (Remote Procedure Call). Setiap RPC memiliki:

    • Nama fungsi
    • Message request sebagai parameter
    • Message response sebagai hasil

gRPC akan otomatis generate client & server stub dari definisi ini.


7. Import File .proto Lain

Jika kamu ingin membuat file .proto modular:

import "common/timestamp.proto";

message Article {
  string id = 1;
  string title = 2;
  common.Timestamp published_at = 3;
}

Struktur ini sangat umum di proyek besar. Pastikan semua path import tersedia di flag --proto_path saat generate kode.


8. Komentar dan Dokumentasi

Komentar di file .proto sangat penting dan akan dibawa saat generate ke beberapa bahasa. Gunakan // untuk komentar satu baris, atau /** ... */ untuk komentar multi-baris.

// User represents a system user.
message User {
  string name = 1; // Full name
}

9. Tips Tambahan

  • Gunakan nama field dengan gaya snake_case untuk konsistensi lintas bahasa.
  • Nomor field sebaiknya tetap (immutable) setelah produksi.
  • Pisahkan setiap service ke file .proto masing-masing agar maintainable.

Template .proto Lengkap

Misalnya kamu sedang membuat layanan UserService, berikut contoh file .proto lengkap:

📄 user.proto

syntax = "proto3";

package user;

option go_package = "github.com/santekno/grpc-user/api/userpb";

// Enum untuk status pengguna
enum Status {
  STATUS_UNKNOWN = 0;
  STATUS_ACTIVE = 1;
  STATUS_INACTIVE = 2;
}

// Struktur data pengguna
message User {
  string id = 1;
  string name = 2;
  int32 age = 3;
  bool is_active = 4;
  Status status = 5;
}

// Request untuk mengambil satu user
message GetUserRequest {
  string id = 1;
}

// Response dari GetUser
message UserResponse {
  User user = 1;
}

// Request untuk membuat user baru
message CreateUserRequest {
  string name = 1;
  int32 age = 2;
}

// Layanan UserService
service UserService {
  rpc GetUser (GetUserRequest) returns (UserResponse);
  rpc CreateUser (CreateUserRequest) returns (UserResponse);
}

Hasil Generate ke Go

Jika kamu menjalankan perintah:

protoc --go_out=. --go-grpc_out=. user.proto

Maka akan terbentuk dua file:

user.pb.go
user_grpc.pb.go

Isi File user_grpc.pb.go akan otomatis berisi:

type UserServiceClient interface {
    GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*UserResponse, error)
    CreateUser(ctx context.Context, in *CreateUserRequest, opts ...grpc.CallOption) (*UserResponse, error)
}

Isi File user.pb.go akan memiliki:

type User struct {
    Id        string
    Name      string
    Age       int32
    IsActive  bool
    Status    Status
}

✅ Diagram Visual Struktur .proto

Berikut diagram arsitektur visual dari struktur file .proto yang bisa kamu gunakan di artikel:

classDiagram
    class UserService {
        +GetUser(request: GetUserRequest): UserResponse
        +CreateUser(request: CreateUserRequest): UserResponse
    }

    class GetUserRequest {
        +string id
    }

    class CreateUserRequest {
        +string name
        +int32 age
    }

    class UserResponse {
        +User user
    }

    class User {
        +string id
        +string name
        +int32 age
        +bool is_active
        +Status status
    }

    class Status {
        <>
        +STATUS_UNKNOWN: int = 0
        +STATUS_ACTIVE: int = 1
        +STATUS_INACTIVE: int = 2
    }

    UserService --> GetUserRequest
    UserService --> CreateUserRequest
    UserService --> UserResponse
    UserResponse --> User
    User --> Status

Kesimpulan

File .proto bukan sekadar definisi data. Ia adalah kontrak, dokumentasi, dan jembatan komunikasi lintas bahasa. Dengan memahami sintaks dasarnya, Anda bisa membangun layanan gRPC yang tidak hanya efisien, tetapi juga robust dan mudah dikelola.

Sebagai seorang engineer, menguasai sintaks Protobuf akan memperluas kemampuan Anda dalam merancang sistem distributed yang modern dan platform-agnostic.

comments powered by Disqus