Node.js Backend Development Bootcamp · Ders

Protobuf IDL ile Hizmetleri ve İletileri Tanımlama

.proto sözleşmeleri yazın ve bunlardan tür güvenli istemci ile sunucu taslakları üretin.

1. ders / 413 adım

Protobuf IDL ile Hizmetleri ve İletileri Tanımlama, CoddyKit'te ücretsiz bir Node.js Backend Development Bootcamp dersidir. Bu, 4 dersinin 1. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Node.js Backend Development Bootcamp öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Node.js Backend Development Bootcamp kursu toplamda 4 dersten oluşur.

Bu dersin bazı bölümleri henüz çevrilmemiş olup İngilizce olarak gösterilmektedir.

Why an IDL?

In a gRPC microservice, the contract comes before the code. You describe your data and your RPC methods in a language-neutral Interface Definition Language (IDL) called .proto, then generate type-safe stubs for Node.js, Go, Java, and more from that single file.

  • One .proto file is the single source of truth shared by client and server.
  • Protocol Buffers (protobuf) is both the IDL and the binary wire format.
  • You never hand-write the serialization code — the compiler does it.

This lesson shows how to write .proto contracts and turn them into JavaScript client and server stubs.

Anatomy of a .proto file

Every modern .proto file starts by declaring the syntax version and a package. The package namespaces your symbols so two services can both define a User without colliding.

  • syntax = "proto3"; — always use proto3 for new services.
  • package — logical namespace, maps to a JS object path after generation.
  • The file groups message (data shapes) and service (RPC methods).
// user.proto
syntax = "proto3";

package users.v1;

// A data shape sent over the wire
message User {
  string id = 1;
  string email = 2;
  bool active = 3;
}

Messages and field numbers

A message is a record of typed fields. The number after the = is the field tag, not a default value. Tags are how protobuf identifies each field on the binary wire — they must be unique within a message and must never change once deployed.

  • Field names can be renamed freely; tags must stay stable for backward compatibility.
  • Tags 1-15 use a single byte, so reserve them for your most frequent fields.
  • Scalar types: string, bool, int32, int64, double, bytes.
message Product {
  string id = 1;          // tag 1 (1 byte on the wire)
  string name = 2;
  int32 stock = 3;
  double price = 4;
  bool discontinued = 5;
}

proto3 to JavaScript type mapping

When you load a .proto with @grpc/proto-loader, each protobuf type maps to a JavaScript value. Knowing the mapping avoids surprises at runtime.

  • string, bool, int32, float, double map to JS string, boolean, number.
  • int64 / uint64 map to a string by default in JS (numbers can exceed Number.MAX_SAFE_INTEGER).
  • bytes becomes a Buffer.
  • Unset proto3 scalars come back as their zero value ("", 0, false) — they are never undefined on the wire.
// What a decoded User object looks like in Node.js
const user = {
  id: 'u_123',      // string -> string
  email: '',         // unset string -> '' (zero value)
  active: false,     // unset bool -> false
  loginCount: '0'    // int64 -> string, not number!
};

console.log(typeof user.loginCount); // 'string'

Defining a service

A service block lists the RPC methods clients can call. Each rpc takes exactly one request message and returns exactly one response message. Wrapping request/response in dedicated messages (rather than passing bare scalars) lets you add fields later without breaking the contract.

  • Method names are PascalCase by convention.
  • Always define a request and a response message per method, even if one is empty.
message GetUserRequest { string id = 1; }
message GetUserResponse { User user = 1; }

service UserService {
  // unary: one request -> one response
  rpc GetUser(GetUserRequest) returns (GetUserResponse);
  rpc CreateUser(CreateUserRequest) returns (User);
}

The four RPC kinds

The stream keyword on either side of an rpc declaration controls the streaming model. The same IDL keyword decides whether your generated handler receives a single value or a stream.

  • Unary: rpc Get(Req) returns (Res) — one in, one out.
  • Server streaming: returns (stream Res) — server pushes many.
  • Client streaming: (stream Req) — client uploads many.
  • Bidirectional: (stream Req) returns (stream Res).
service OrderService {
  rpc GetOrder(GetOrderRequest) returns (Order);
  rpc ListOrders(ListOrdersRequest) returns (stream Order);
  rpc ImportOrders(stream Order) returns (ImportSummary);
  rpc LiveOrders(stream OrderEvent) returns (stream OrderEvent);
}

Enums, repeated, and nested messages

Beyond scalars, protobuf gives you composite shapes for real-world data.

  • enum — a closed set of values; the first member must be 0 and is the default.
  • repeated — an ordered list; decodes to a JS Array.
  • Nested messages model structured sub-records.

Prefix enum members to avoid name clashes, since enum values share the enclosing scope.

enum OrderStatus {
  ORDER_STATUS_UNSPECIFIED = 0; // required zero default
  ORDER_STATUS_PENDING = 1;
  ORDER_STATUS_SHIPPED = 2;
}

message Order {
  string id = 1;
  OrderStatus status = 2;
  repeated LineItem items = 3; // -> JS Array
}

message LineItem {
  string sku = 1;
  int32 qty = 2;
}

Loading the contract in Node.js

In Node you generate stubs at runtime with @grpc/proto-loader plus @grpc/grpc-js. The loader parses the .proto and loadPackageDefinition turns it into a navigable JS object keyed by your package path.

  • keepCase: true preserves field names exactly as written in the proto.
  • longs: String keeps 64-bit ints safe as strings.
  • The package path users.v1 becomes proto.users.v1.
const protoLoader = require('@grpc/proto-loader');
const grpc = require('@grpc/grpc-js');

const pkgDef = protoLoader.loadSync('user.proto', {
  keepCase: true,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true,
});

const proto = grpc.loadPackageDefinition(pkgDef);
const UserService = proto.users.v1.UserService;

Implementing the server stub

The generated UserService gives you a service definition you register handlers against. Each unary handler receives (call, callback); call.request is your decoded request message, and you reply via the Node-style callback(err, response).

  • Return a gRPC status by passing an error with a code from grpc.status.
  • The response object must match the response message fields.
const server = new grpc.Server();

server.addService(UserService.service, {
  GetUser(call, callback) {
    const { id } = call.request;
    const user = db.find(id);
    if (!user) {
      return callback({
        code: grpc.status.NOT_FOUND,
        message: `User ${id} not found`,
      });
    }
    callback(null, { user });
  },
});

Calling from the client stub

The same generated UserService is also a client constructor. You instantiate it with a target address and credentials, then call methods directly. Each unary call takes the request object and a Node-style callback.

  • credentials.createInsecure() for local/dev; use TLS in production.
  • The request and response are plain JS objects matching the proto messages.
const client = new UserService(
  'localhost:50051',
  grpc.credentials.createInsecure()
);

client.GetUser({ id: 'u_123' }, (err, res) => {
  if (err) {
    console.error(err.code, err.message);
    return;
  }
  console.log(res.user.email);
});

Evolving the contract safely

A contract is only useful if it can change without breaking deployed clients. proto3 makes additive evolution safe when you follow a few rules.

  • Add new fields with new, never-before-used tag numbers — old clients ignore them.
  • Never reuse or renumber tags; mark removed tags with reserved.
  • Renaming a field is wire-compatible (tag is what matters), but breaks JSON/text usage.
  • Use reserved for both removed tag numbers and names to prevent accidental reuse.
message User {
  reserved 4, 5;              // retired tags, never reuse
  reserved "phone";          // retired field name
  string id = 1;
  string email = 2;
  bool active = 3;
  string display_name = 6;   // safe additive change
}

Quick Check

You need to remove the deprecated phone field (tag 4) from a deployed User message. What is the correct, backward-compatible way to do it?

Recap

You learned to design and consume gRPC contracts with Protobuf IDL:

  • A .proto file with syntax = "proto3" and a package is the single source of truth for client and server.
  • message defines typed records; the number after each field is its stable wire tag, not a default.
  • service + rpc declare methods; the stream keyword selects unary, server-, client-, or bidirectional streaming.
  • enum, repeated, and nested messages model richer data; int64 decodes to a JS string.
  • In Node, @grpc/proto-loader + grpc.loadPackageDefinition generate both the server service and the client constructor.
  • Evolve contracts additively and protect retired tags/names with reserved.
Başlamak ücretsiz

Yapay zeka eğitmeniyle JavaScript öğren — ücretsiz

Tarayıcında gerçek kod yaz ve çalıştır, 7/24 yapay zeka eğitmeninden anında yardım al; web'de ya da uygulamada kaldığın yerden devam et.

Kurslar
22
Dersler
92

Sıkça Sorulan Sorular

“Protobuf IDL ile Hizmetleri ve İletileri Tanımlama” dersi ücretsiz mi?

Evet — “Protobuf IDL ile Hizmetleri ve İletileri Tanımlama” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Node.js Backend Development Bootcamp kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Node.js Backend Development Bootcamp kursu toplamda 4 dersten oluşur.

“Protobuf IDL ile Hizmetleri ve İletileri Tanımlama” dersinde ne öğreneceğim?

.proto sözleşmeleri yazın ve bunlardan tür güvenli istemci ile sunucu taslakları üretin. Node.js Backend Development Bootcamp ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

Node.js Backend Development Bootcamp öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te Node.js Backend Development Bootcamp, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 1. dersidir.

“Protobuf IDL ile Hizmetleri ve İletileri Tanımlama” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu Node.js Backend Development Bootcamp dersinde kod yazıp çalıştırabilir miyim?

Evet. Her Node.js Backend Development Bootcamp dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. Protobuf IDL ile Hizmetleri ve İletileri Tanımlama
  2. Tekli, Sunucu, İstemci ve Çift Yönlü Akış RPC'leri
  3. Araya Giriciler, Son Tarihler ve Üst Veriler
  4. Proto Evrimi ve Geriye Dönük Uyumluluk
← Node.js Backend Development Bootcamp Sayfasına Dön