grpc-protobuf
サービス間通信で利用されるgRPCやProtocol Buffersに関する専門用語が出た際に、関連情報を提供するSkill。
📜 元の英語説明(参考)
gRPC and Protocol Buffers for service-to-service communication. Use when user mentions "grpc", "protobuf", "protocol buffers", ".proto", "grpcurl", "service definition", "RPC", "streaming", "buf", "protoc", or building gRPC services.
🇯🇵 日本人クリエイター向け解説
サービス間通信で利用されるgRPCやProtocol Buffersに関する専門用語が出た際に、関連情報を提供するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o grpc-protobuf.zip https://jpskill.com/download/6094.zip && unzip -o grpc-protobuf.zip && rm grpc-protobuf.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/6094.zip -OutFile "$d\grpc-protobuf.zip"; Expand-Archive "$d\grpc-protobuf.zip" -DestinationPath $d -Force; ri "$d\grpc-protobuf.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
grpc-protobuf.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
grpc-protobufフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-17
- 取得日時
- 2026-05-17
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
gRPCとProtocol Buffers
Protobufの基本
Protocol Buffers (protobuf) は、言語に依存しないバイナリシリアライゼーション形式です。スキーマは.protoファイルで定義します。
syntax = "proto3";
package myapp.v1;
option go_package = "github.com/myorg/myapp/gen/myappv1";
message User {
string id = 1;
string name = 2;
string email = 3;
int64 created_at = 4;
repeated string roles = 5; // ordered list
Address address = 6; // nested message
UserStatus status = 7; // enum
map<string, string> metadata = 8; // key-value pairs
}
message Address {
string street = 1;
string city = 2;
string country = 3;
}
enum UserStatus {
USER_STATUS_UNSPECIFIED = 0; // required zero value
USER_STATUS_ACTIVE = 1;
USER_STATUS_INACTIVE = 2;
}
スカラ型
| Protobuf | Go | Python | Node | Java |
|---|---|---|---|---|
| double | float64 | float | number | double |
| float | float32 | float | number | float |
| int32 | int32 | int | number | int |
| int64 | int64 | int | number | long |
| bool | bool | bool | boolean | boolean |
| string | string | str | string | String |
| bytes | []byte | bytes | Buffer | ByteString |
フィールド番号1-15はワイヤー上で1バイトを使用するため、頻繁に使用するフィールドに予約してください。フィールド番号を再利用しないでください。未設定とデフォルトを区別するには、ラッパー型(google.protobuf.StringValue)を使用します。
サービス定義
service UserService {
rpc GetUser(GetUserRequest) returns (GetUserResponse); // unary
rpc ListUsers(ListUsersRequest) returns (stream User); // server streaming
rpc UploadUsers(stream User) returns (UploadUsersResponse); // client streaming
rpc SyncUsers(stream SyncRequest) returns (stream SyncResponse); // bidirectional
}
message GetUserRequest { string id = 1; }
message GetUserResponse { User user = 1; }
message ListUsersRequest { int32 page_size = 1; string page_token = 2; }
protocによるコード生成
# Install: brew install protobuf (macOS) / apt install protobuf-compiler (Linux)
# Go
protoc --go_out=. --go-grpc_out=. proto/user.proto
# Python
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. proto/user.proto
# Node.js
grpc_tools_node_protoc --js_out=import_style=commonjs:. --grpc_out=. proto/user.proto
bufツール(現代的なprotocの代替)
# buf.yaml
version: v2
modules:
- path: proto
lint:
use: [STANDARD]
breaking:
use: [FILE]
# buf.gen.yaml
version: v2
plugins:
- remote: buf.build/protocolbuffers/go
out: gen/go
opt: paths=source_relative
- remote: buf.build/grpc/go
out: gen/go
opt: paths=source_relative
buf lint # Lint proto files
buf breaking --against '.git#branch=main' # Detect breaking changes
buf generate # Generate code
bufはスタイルを強制します。パッケージ名はディレクトリと一致し、enumのゼロ値は_UNSPECIFIEDで終わり、サービス名はServiceで終わります。
gRPCのパターン
- 単項 (Unary): 1つのリクエスト、1つのレスポンス。CRUDやルックアップに使用します。
- サーバーサイドストリーミング (Server streaming): 1つのリクエスト、レスポンスのストリーム。大規模な結果セットやフィードに使用します。
- クライアントサイドストリーミング (Client streaming): リクエストのストリーム、1つのレスポンス。アップロードやバッチ取り込みに使用します。
- 双方向ストリーミング (Bidirectional): 両側が独立してストリームします。チャットやリアルタイム同期に使用します。
Node.jsにおけるgRPC
const grpc = require("@grpc/grpc-js");
const protoLoader = require("@grpc/proto-loader");
const packageDef = protoLoader.loadSync("proto/user.proto", {
keepCase: true, longs: String, enums: String, defaults: true, oneofs: true,
});
const proto = grpc.loadPackageDefinition(packageDef).myapp.v1;
// Server
function getUser(call, callback) {
callback(null, { user: { id: call.request.id, name: "Alice" } });
}
function listUsers(call) {
for (let i = 0; i < 10; i++) call.write({ id: String(i), name: `User ${i}` });
call.end();
}
const server = new grpc.Server();
server.addService(proto.UserService.service, { getUser, listUsers });
server.bindAsync("0.0.0.0:50051", grpc.ServerCredentials.createInsecure(), () => {});
// Client
const client = new proto.UserService("localhost:50051", grpc.credentials.createInsecure());
client.getUser({ id: "123" }, (err, res) => {
if (err) return console.error(`Code: ${err.code}, Message: ${err.details}`);
console.log(res.user);
});
const stream = client.listUsers({ page_size: 10 });
stream.on("data", (user) => console.log(user));
stream.on("end", () => console.log("done"));
PythonにおけるgRPC
import grpc
from concurrent import futures
import user_pb2, user_pb2_grpc
class UserServiceServicer(user_pb2_grpc.UserServiceServicer):
def GetUser(self, request, context):
if not request.id:
context.abort(grpc.StatusCode.INVALID_ARGUMENT, "id required")
return user_pb2.GetUserResponse(user=user_pb2.User(id=request.id, name="Alice"))
def ListUsers(self, request, context):
for i in range(10):
yield user_pb2.User(id=str(i), name=f"User {i}")
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
user_pb2_grpc.add_UserServiceServicer_to_server(UserServiceServicer(), server)
server.add_insecure_port("[::]:50051")
server.start()
server.wait_for_termination()
# Client
channel = grpc.insecure_channel("localhost:50051")
stub = user_pb2_grpc.UserServiceStub(channel)
try:
response = stub.GetUser(user_pb2.GetUserRequest(id="123"), timeout=5)
except grpc.RpcError as e:
print(f"Code: {e.code()}, Details: {e.details()}")
for user in stub.ListUsers(user_pb2.ListUsersRequest(page_size=10)):
print(user)
GoにおけるgRPC
package main
import (
"context"
"fmt"
"log"
"net"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
pb "github.com/ 📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
gRPC and Protocol Buffers
Protobuf Basics
Protocol Buffers (protobuf) is a language-neutral binary serialization format. Define schemas in .proto files.
syntax = "proto3";
package myapp.v1;
option go_package = "github.com/myorg/myapp/gen/myappv1";
message User {
string id = 1;
string name = 2;
string email = 3;
int64 created_at = 4;
repeated string roles = 5; // ordered list
Address address = 6; // nested message
UserStatus status = 7; // enum
map<string, string> metadata = 8; // key-value pairs
}
message Address {
string street = 1;
string city = 2;
string country = 3;
}
enum UserStatus {
USER_STATUS_UNSPECIFIED = 0; // required zero value
USER_STATUS_ACTIVE = 1;
USER_STATUS_INACTIVE = 2;
}
Scalar Types
| Protobuf | Go | Python | Node | Java |
|---|---|---|---|---|
| double | float64 | float | number | double |
| float | float32 | float | number | float |
| int32 | int32 | int | number | int |
| int64 | int64 | int | number | long |
| bool | bool | bool | boolean | boolean |
| string | string | str | string | String |
| bytes | []byte | bytes | Buffer | ByteString |
Field numbers 1-15 use one byte on the wire -- reserve them for frequent fields. Never reuse field numbers. Use wrapper types (google.protobuf.StringValue) to distinguish unset from default.
Service Definitions
service UserService {
rpc GetUser(GetUserRequest) returns (GetUserResponse); // unary
rpc ListUsers(ListUsersRequest) returns (stream User); // server streaming
rpc UploadUsers(stream User) returns (UploadUsersResponse); // client streaming
rpc SyncUsers(stream SyncRequest) returns (stream SyncResponse); // bidirectional
}
message GetUserRequest { string id = 1; }
message GetUserResponse { User user = 1; }
message ListUsersRequest { int32 page_size = 1; string page_token = 2; }
Code Generation with protoc
# Install: brew install protobuf (macOS) / apt install protobuf-compiler (Linux)
# Go
protoc --go_out=. --go-grpc_out=. proto/user.proto
# Python
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. proto/user.proto
# Node.js
grpc_tools_node_protoc --js_out=import_style=commonjs:. --grpc_out=. proto/user.proto
buf Tool (Modern protoc Replacement)
# buf.yaml
version: v2
modules:
- path: proto
lint:
use: [STANDARD]
breaking:
use: [FILE]
# buf.gen.yaml
version: v2
plugins:
- remote: buf.build/protocolbuffers/go
out: gen/go
opt: paths=source_relative
- remote: buf.build/grpc/go
out: gen/go
opt: paths=source_relative
buf lint # Lint proto files
buf breaking --against '.git#branch=main' # Detect breaking changes
buf generate # Generate code
buf enforces style: package names match directories, enum zero values end in _UNSPECIFIED, service names end in Service.
gRPC Patterns
- Unary: one request, one response. Use for CRUD, lookups.
- Server streaming: one request, stream of responses. Use for large result sets, feeds.
- Client streaming: stream of requests, one response. Use for uploads, batch ingestion.
- Bidirectional: both sides stream independently. Use for chat, real-time sync.
gRPC in Node.js
const grpc = require("@grpc/grpc-js");
const protoLoader = require("@grpc/proto-loader");
const packageDef = protoLoader.loadSync("proto/user.proto", {
keepCase: true, longs: String, enums: String, defaults: true, oneofs: true,
});
const proto = grpc.loadPackageDefinition(packageDef).myapp.v1;
// Server
function getUser(call, callback) {
callback(null, { user: { id: call.request.id, name: "Alice" } });
}
function listUsers(call) {
for (let i = 0; i < 10; i++) call.write({ id: String(i), name: `User ${i}` });
call.end();
}
const server = new grpc.Server();
server.addService(proto.UserService.service, { getUser, listUsers });
server.bindAsync("0.0.0.0:50051", grpc.ServerCredentials.createInsecure(), () => {});
// Client
const client = new proto.UserService("localhost:50051", grpc.credentials.createInsecure());
client.getUser({ id: "123" }, (err, res) => {
if (err) return console.error(`Code: ${err.code}, Message: ${err.details}`);
console.log(res.user);
});
const stream = client.listUsers({ page_size: 10 });
stream.on("data", (user) => console.log(user));
stream.on("end", () => console.log("done"));
gRPC in Python
import grpc
from concurrent import futures
import user_pb2, user_pb2_grpc
class UserServiceServicer(user_pb2_grpc.UserServiceServicer):
def GetUser(self, request, context):
if not request.id:
context.abort(grpc.StatusCode.INVALID_ARGUMENT, "id required")
return user_pb2.GetUserResponse(user=user_pb2.User(id=request.id, name="Alice"))
def ListUsers(self, request, context):
for i in range(10):
yield user_pb2.User(id=str(i), name=f"User {i}")
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
user_pb2_grpc.add_UserServiceServicer_to_server(UserServiceServicer(), server)
server.add_insecure_port("[::]:50051")
server.start()
server.wait_for_termination()
# Client
channel = grpc.insecure_channel("localhost:50051")
stub = user_pb2_grpc.UserServiceStub(channel)
try:
response = stub.GetUser(user_pb2.GetUserRequest(id="123"), timeout=5)
except grpc.RpcError as e:
print(f"Code: {e.code()}, Details: {e.details()}")
for user in stub.ListUsers(user_pb2.ListUsersRequest(page_size=10)):
print(user)
gRPC in Go
package main
import (
"context"
"fmt"
"log"
"net"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
pb "github.com/myorg/myapp/gen/myappv1"
)
type server struct{ pb.UnimplementedUserServiceServer }
func (s *server) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.GetUserResponse, error) {
if req.Id == "" {
return nil, status.Error(codes.InvalidArgument, "id required")
}
return &pb.GetUserResponse{User: &pb.User{Id: req.Id, Name: "Alice"}}, nil
}
func (s *server) ListUsers(req *pb.ListUsersRequest, stream pb.UserService_ListUsersServer) error {
for i := 0; i < 10; i++ {
if err := stream.Send(&pb.User{Id: fmt.Sprintf("%d", i)}); err != nil {
return err
}
}
return nil
}
func main() {
lis, _ := net.Listen("tcp", ":50051")
s := grpc.NewServer()
pb.RegisterUserServiceServer(s, &server{})
log.Fatal(s.Serve(lis))
}
Go client:
conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
defer conn.Close()
client := pb.NewUserServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
resp, err := client.GetUser(ctx, &pb.GetUserRequest{Id: "123"})
if err != nil {
st, _ := status.FromError(err)
log.Printf("Code: %s, Message: %s", st.Code(), st.Message())
}
grpcurl for Testing
# Install: brew install grpcurl
# Server must have reflection enabled, or use -import-path/-proto flags
grpcurl -plaintext localhost:50051 list # list services
grpcurl -plaintext localhost:50051 describe myapp.v1.UserService # describe service
grpcurl -plaintext -d '{"id":"123"}' localhost:50051 myapp.v1.UserService/GetUser
grpcurl -plaintext -H 'authorization: Bearer tok' -d '{"id":"123"}' \
localhost:50051 myapp.v1.UserService/GetUser # with metadata
grpcurl -plaintext -import-path ./proto -proto user.proto \
-d '{"page_size":10}' localhost:50051 myapp.v1.UserService/ListUsers
Enable reflection: Go reflection.Register(s), Python grpc_reflection.v1alpha.reflection.enable_server_reflection(names, server), Node @grpc/reflection.
Error Handling: gRPC Status Codes
| Code | Num | Use For |
|---|---|---|
| OK | 0 | Success |
| CANCELLED | 1 | Client cancelled |
| INVALID_ARGUMENT | 3 | Bad input |
| DEADLINE_EXCEEDED | 4 | Timeout |
| NOT_FOUND | 5 | Resource missing |
| ALREADY_EXISTS | 6 | Conflict on create |
| PERMISSION_DENIED | 7 | Lacks permission |
| RESOURCE_EXHAUSTED | 8 | Rate limit / quota |
| FAILED_PRECONDITION | 9 | System not in required state |
| UNIMPLEMENTED | 12 | Method not implemented |
| INTERNAL | 13 | Unexpected server error |
| UNAVAILABLE | 14 | Transient -- client should retry |
| UNAUTHENTICATED | 16 | No valid credentials |
Do not use UNKNOWN as a catch-all. Return UNAVAILABLE for transient failures so clients retry.
Metadata
Metadata is the gRPC equivalent of HTTP headers. Keys are strings; binary values use keys ending in -bin.
// Go: read incoming metadata
md, _ := metadata.FromIncomingContext(ctx)
token := md.Get("authorization")
// Go: send outgoing metadata
ctx = metadata.AppendToOutgoingContext(ctx, "authorization", "Bearer tok")
# Python: read
token = context.invocation_metadata() # list of (key, value) tuples
# Python: send
stub.GetUser(request, metadata=[("authorization", "Bearer tok")])
Deadlines and Timeouts
Always set deadlines. A missing deadline holds resources indefinitely. Propagate the incoming context in chained calls so the overall deadline is respected.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
response = stub.GetUser(request, timeout=5)
const deadline = new Date(Date.now() + 5000);
client.getUser({ id: "123" }, { deadline }, callback);
Health Checking
Use the standard grpc.health.v1.Health protocol. Do not invent your own.
import "google.golang.org/grpc/health"
import healthpb "google.golang.org/grpc/health/grpc_health_v1"
hs := health.NewServer()
healthpb.RegisterHealthServer(s, hs)
hs.SetServingStatus("myapp.v1.UserService", healthpb.HealthCheckResponse_SERVING)
grpcurl -plaintext localhost:50051 grpc.health.v1.Health/Check
Common Patterns
Microservice API Structure
proto/myapp/
user/v1/user.proto
user/v1/user_service.proto
order/v1/order.proto
order/v1/order_service.proto
Keep request/response messages with the service. Share domain messages via imports. Use v1 package suffix for versioning.
Streaming Data Feed
service PriceFeed {
rpc Subscribe(SubscribeRequest) returns (stream PriceUpdate);
}
message SubscribeRequest { repeated string symbols = 1; }
message PriceUpdate { string symbol = 1; double price = 2; int64 timestamp = 3; }
Client reconnects on UNAVAILABLE with exponential backoff. Use keepalive settings to detect dead connections.
gRPC vs REST
| Concern | gRPC | REST |
|---|---|---|
| Serialization | Protobuf (binary, compact) | JSON (text, readable) |
| Schema | Required (.proto) | Optional (OpenAPI) |
| Streaming | Native (4 patterns) | SSE / WebSocket workarounds |
| Browser | Needs grpc-web proxy | Native |
| Tooling | protoc/buf + plugins | curl, any HTTP client |
| Performance | Lower latency, smaller payload | Higher latency, larger payload |
| Code gen | Built-in, strongly typed | Varies |
| Load balancing | L7 HTTP/2-aware required | Any HTTP LB |
Use gRPC for internal service-to-service calls where performance, type safety, and streaming matter. Use REST for public APIs and browser clients. Both coexist well -- REST at the edge, gRPC internally.