본문으로 건너뛰기
Previous
Next
gRPC Complete Guide | Protocol Buffers· Service Definitions

gRPC Complete Guide | Protocol Buffers· Service Definitions

gRPC Complete Guide | Protocol Buffers· Service Definitions

이 글의 핵심

A complete guide to building high-performance APIs with gRPC?�Protocol Buffers, service definitions, Unary and Streaming RPC, and hands-on Node.js and Go examples including errors, JWT metadata, and Docker deployment.

What this post covers

This is a complete guide to building high-performance APIs with gRPC. It covers Protocol Buffers, service definitions, Unary and Streaming RPC, and hands-on Node.js and Go examples.

From the field: After migrating an internal API from REST to gRPC, we cut response latency by about 5× and reduced network bandwidth by roughly 70%.

Introduction: ?�Our REST API feels slow??

Real-world scenarios

Scenario 1: JSON parsing is expensive

Large payloads feel sluggish. gRPC uses efficient binary serialization.

Scenario 2: Weak type safety

The API contract is vague. gRPC gives you strong, generated types.

Scenario 3: You need streaming

Classic request/response REST is not enough. gRPC supports bidirectional streaming.


1. What is gRPC?

Key characteristics

gRPC is a high-performance RPC framework originally developed by Google.

Main benefits:

  • Performance: binary protocol over HTTP/2
  • Type safety: Protocol Buffers as the interface definition language
  • Streaming: server, client, and bidirectional streaming
  • Polyglot: first-class support for many languages
  • HTTP/2: multiplexing, header compression, and efficient connections

Rough performance comparison (illustrative, not a benchmark):

  • REST (JSON): ~100 ms, ~10 KB payload
  • gRPC (Protobuf): ~20 ms, ~2 KB payload

2. Protocol Buffers

.proto files

// user.proto
syntax = "proto3";
package user;
message User {
  int32 id = 1;
  string name = 2;
  string email = 3;
  int32 age = 4;
}
message GetUserRequest {
  int32 id = 1;
}
message GetUserResponse {
  User user = 1;
}
message ListUsersRequest {
  int32 page = 1;
  int32 page_size = 2;
}
message ListUsersResponse {
  repeated User users = 1;
  int32 total = 2;
}
service UserService {
  rpc GetUser(GetUserRequest) returns (GetUserResponse);
  rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);
  rpc CreateUser(User) returns (User);
}

3. Node.js implementation

Install dependencies

npm install @grpc/grpc-js @grpc/proto-loader

Server

// server.ts
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
const PROTO_PATH = './user.proto';
const packageDefinition = protoLoader.loadSync(PROTO_PATH);
const userProto = grpc.loadPackageDefinition(packageDefinition).user as any;
const users = [
  { id: 1, name: 'John', email: '[email protected]', age: 30 },
  { id: 2, name: 'Jane', email: '[email protected]', age: 25 },
];
const server = new grpc.Server();
server.addService(userProto.UserService.service, {
  getUser: (call: any, callback: any) => {
    const user = users.find(u => u.id === call.request.id);
    
    if (user) {
      callback(null, { user });
    } else {
      callback({
        code: grpc.status.NOT_FOUND,
        message: 'User not found',
      });
    }
  },
  listUsers: (call: any, callback: any) => {
    callback(null, { users, total: users.length });
  },
  createUser: (call: any, callback: any) => {
    const newUser = {
      id: users.length + 1,
      ...call.request,
    };
    users.push(newUser);
    callback(null, newUser);
  },
});
server.bindAsync(
  '0.0.0.0:50051',
  grpc.ServerCredentials.createInsecure(),
  () => {
    console.log('gRPC server running on :50051');
    server.start();
  }
);

Client

// client.ts
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
const PROTO_PATH = './user.proto';
const packageDefinition = protoLoader.loadSync(PROTO_PATH);
const userProto = grpc.loadPackageDefinition(packageDefinition).user as any;
const client = new userProto.UserService(
  'localhost:50051',
  grpc.credentials.createInsecure()
);
// GetUser
client.getUser({ id: 1 }, (error: any, response: any) => {
  if (error) {
    console.error('Error:', error);
  } else {
    console.log('User:', response.user);
  }
});
// ListUsers
client.listUsers({ page: 1, page_size: 10 }, (error: any, response: any) => {
  if (error) {
    console.error('Error:', error);
  } else {
    console.log('Users:', response.users);
  }
});
// CreateUser
client.createUser(
  { name: 'Bob', email: '[email protected]', age: 35 },
  (error: any, response: any) => {
    if (error) {
      console.error('Error:', error);
    } else {
      console.log('Created:', response);
    }
  }
);

4. Streaming

Server streaming

service LogService {
  rpc StreamLogs(StreamLogsRequest) returns (stream LogEntry);
}
// Server
streamLogs: (call: any) => {
  const logs = [
    { message: 'Log 1', timestamp: Date.now() },
    { message: 'Log 2', timestamp: Date.now() },
    { message: 'Log 3', timestamp: Date.now() },
  ];
  logs.forEach((log) => {
    call.write(log);
  });
  call.end();
},
// Client
const call = client.streamLogs({});
call.on('data', (log: any) => {
  console.log('Log:', log);
});
call.on('end', () => {
  console.log('Stream ended');
});

Bidirectional streaming

service ChatService {
  rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}
// Server
chat: (call: any) => {
  call.on('data', (message: any) => {
    console.log('Received:', message);
    
    // Echo back to the same client (example)
    call.write({
      user: message.user,
      text: message.text,
      timestamp: Date.now(),
    });
  });
  call.on('end', () => {
    call.end();
  });
},
// Client
const call = client.chat();
call.on('data', (message: any) => {
  console.log('Message:', message);
});
call.write({ user: 'John', text: 'Hello!' });

5. Go implementation

Server

// server.go
package main
import (
	"context"
	"log"
	"net"
	pb "myapp/proto"
	"google.golang.org/grpc"
)
type server struct {
	pb.UnimplementedUserServiceServer
}
func (s *server) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.GetUserResponse, error) {
	user := &pb.User{
		Id:    req.Id,
		Name:  "John",
		Email: "[email protected]",
		Age:   30,
	}
	return &pb.GetUserResponse{User: user}, nil
}
func main() {
	lis, err := net.Listen("tcp", ":50051")
	if err != nil {
		log.Fatalf("Failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterUserServiceServer(s, &server{})
	log.Println("gRPC server running on :50051")
	if err := s.Serve(lis); err != nil {
		log.Fatalf("Failed to serve: %v", err)
	}
}

6. Error handling

import * as grpc from '@grpc/grpc-js';
// Server
getUser: (call: any, callback: any) => {
  const user = findUser(call.request.id);
  if (!user) {
    return callback({
      code: grpc.status.NOT_FOUND,
      message: 'User not found',
      details: 'No user with the given ID exists',
    });
  }
  callback(null, { user });
},
// Client
client.getUser({ id: 999 }, (error: any, response: any) => {
  if (error) {
    if (error.code === grpc.status.NOT_FOUND) {
      console.error('User not found');
    } else {
      console.error('Error:', error.message);
    }
  } else {
    console.log('User:', response.user);
  }
});

7. Authentication

JWT metadata

// Client
import * as grpc from '@grpc/grpc-js';
const metadata = new grpc.Metadata();
metadata.add('authorization', `Bearer ${token}`);
client.getUser({ id: 1 }, metadata, (error: any, response: any) => {
  // ...
});
// Server
getUser: (call: any, callback: any) => {
  const metadata = call.metadata;
  const auth = metadata.get('authorization')[0];
  if (!auth || !verifyToken(auth)) {
    return callback({
      code: grpc.status.UNAUTHENTICATED,
      message: 'Invalid token',
    });
  }
  // ...
},

8. Deployment

Docker

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 50051
CMD ["node", "server.js"]

Interview preparation

Protobuf, streaming, and HTTP/2 show up often in microservices and backend interviews. Pair this guide with [Developer job search ??practical tips](/en/blog/developer-job-hunting-practical-tips/ and [Coding test strategy guide](/en/blog/coding-test-strategy-guide/ to cover both system design and hiring loops.


Summary and checklist

Key takeaways

  • gRPC: high-performance RPC framework
  • Protocol Buffers: compact binary serialization
  • Type safety: explicit messages and generated code
  • Streaming: server, client, and bidirectional
  • HTTP/2: multiplexing and efficient connections
  • Polyglot: broad language support

Implementation checklist

  • Author .proto files and version your schemas
  • Implement the server
  • Implement the client
  • Add streaming where needed
  • Handle errors with grpc.status codes
  • Add authentication (for example metadata + TLS in production)
  • Package and deploy (for example Docker + orchestrator)

  • [GraphQL complete guide](/en/blog/graphql-complete-guide/
  • [Microservices architecture guide](/en/blog/microservices-architecture-guide/
  • [Kubernetes practical guide](/en/blog/kubernetes-practical-guide/

Keywords covered in this post

gRPC, Protocol Buffers, RPC, Microservices, API, Performance, Backend

Frequently asked questions (FAQ)

Q. gRPC vs REST?�which should I choose?

A. gRPC is usually much faster for internal RPC. REST is simpler and better suited to browsers and public HTTP APIs. Use gRPC between services; expose REST or GraphQL at the edge when needed.

Q. Can I use gRPC in the browser?

A. Use gRPC-Web for limited browser support. For most web apps, REST or GraphQL remains the pragmatic choice.

Q. Do I have to learn Protocol Buffers?

A. Yes, but the basics are small. Think of .proto files as typed, versioned API contracts?�similar in spirit to JSON Schema, but compiled to efficient code.

Q. Is gRPC safe for production?

A. Yes. Large organizations run gRPC at scale. Pair it with TLS, robust load balancing, health checks, and observability (metrics, tracing, structured logs).


?�주 묻는 질문 (FAQ)

Q. ???�용???�무?�서 ?�제 ?�나??

A. Build high-performance APIs with gRPC: Protocol Buffers, service definitions, Unary/Streaming RPC, Node.js and Go exampl???�무?�서????본문???�제?� ?�택 가?�드�?참고???�용?�면 ?�니??

Q. ?�행?�로 ?�으�?좋�? 글?�?

A. �?글 ?�단???�전 글 ?�는 관??글 링크�??�라가�??�서?��?배울 ???�습?�다. C++ ?�리�?목차?�서 ?�체 ?�름???�인?????�습?�다.

Q. ??깊이 공�??�려�?

A. cppreference?� ?�당 ?�이브러�?공식 문서�?참고?�세?? 글 말�???참고 ?�료 링크???�용?�면 좋습?�다.


같이 보면 좋�? 글 (?��? 링크)

??주제?� ?�결?�는 ?�른 글?�니??

  • [GraphQL Complete Guide | Schema· Resolver](/en/blog/graphql-complete-guide/
  • [Microservices Architecture Guide | Design· Patterns](/en/blog/microservices-architecture-guide/
  • [API Design Complete Guide](/en/blog/api-design-rest-graphql-grpc-comparison/
  • [Coding Test Complete Preparation Complete Guide](/en/blog/coding-test-strategy-guide/

??글?�서 ?�루???�워??(관??검?�어)

gRPC, Protocol Buffers, RPC, Microservices, API, Performance, Backend ?�으�?검?�하?�면 ??글???��????�니??