🛠️

Protocol Buffers(proto3)の共通定義を切り出して再利用する方法

2025/04/01に公開

今回は、共通のprotobuf定義を切り出して再利用する方法を説明します。
共通の定義を一元化することで、コード生成時に、重複した定義エラーになるのを防ぐことができます。

参考のリポジトリは以下です

https://github.com/rensawamo/common-proto

フォルダ構成

まずは、フォルダ構成について、説明します。

.
├── buf.lock
├── buf.yaml
├── Makefile
├── README.md
├── proto
│   ├── common
│   │   └── common/v1
│   │       └── common.proto
│   ├── customerapi
│   │   └── customer/v1
│   │       └── customer.proto
│   └── employeeapi
│       └── employee/v1
│           └── employee.proto
└── output/go(other)
    ├── gen
    ├── Makefile
    ├── README.md
    └── buf.gen.yaml

proto ディレクトリ

proto/ ディレクトリには、Protocol Buffers(proto3) の定義ファイルが格納されています。

common/v1/common.proto → 共通で使用するENUM定義しています。

具体的には、以下のような形です。
今回は、customerapiとemployeeapiで共通で使用するENUM定義を作成してみました。
例えば、性別のENUMなども、仕様によっては必要になるケースがありそうです。

syntax = "proto3";

package common.v1;

enum Prefecture {
  PREFECTURE_UNKNOWN_UNSPECIFIED = 0;
  PREFECTURE_TOKYO = 1;
  PREFECTURE_KANAGAWA = 2;
  PREFECTURE_CHIBA = 3;
  PREFECTURE_SAITAMA = 4;
  PREFECTURE_IBARAKI = 5;
  PREFECTURE_TOCHIGI = 6;
  PREFECTURE_GUNMA = 7;
}

customer/employee protoファイル

common.protoをインポートします。
以下のように、インポート可能です!

syntax = "proto3";

package employee.v1;

import "common/v1/common.proto";

message Employee {
  string id = 1;
  string name = 2;
  string department = 3;
  common.v1.Prefecture hometown = 4;
}

buf.yamlファイルを確認しよう!

bufのバージョン2を利用しています。
バージョン2から、複数のモジュールを一つの buf.yaml ファイルで管理できるようになりました。

以前は buf.work.yaml で複雑な管理が必要でしたが、バージョン2では buf.yaml に統合されてシンプルになりました!

https://buf.build/docs/configuration/v2/buf-yaml/

# For details on buf.yaml configuration, visit https://buf.build/docs/configuration/v2/buf-yaml
version: v2
breaking:
  use:
    - PACKAGE
lint:
  use:
    - STANDARD
modules:
  - path: proto/common
  - path: proto/customerapi
  - path: proto/employeeapi
deps:
  - buf.build/googleapis/googleapis

コード生成を確認しよう!

今回は、dart、go、java、typescriptで
上記で定義した、protoファイルからコード生成してみました。

goの場合は、以下のようにコード生成ができていることが確認できました。
以下のように、共通protoファイルを切り出すことで、
重複定義エラーを防ぐことが可能です!

.
├── output/go
│   └── gen
│       ├── common
│       │   └── v1
│       │       └── common.pb.go
│       ├── customer
│       │   └── v1
│       │       └── customer.pb.go
│       ├── employee
│       │   └── v1
│       │       └── employee.pb.go
│       └── google
│           └── protobuf
│               └── timestamp.pb.go
├── buf.gen.yaml
├── Makefile
└── README.md

buf.gen.yamlファイルを確認しよう!

コード生成には、buf.gen.yamlを定義する必要があります。

https://buf.build/docs/configuration/v2/buf-gen-yaml/

version: v2
clean: true
managed:
  enabled: true
  override:
    - file_option: go_package_prefix
      value: https://github.com/rensawamo/common-proto/output/go/gen
plugins:
  - remote: buf.build/protocolbuffers/go:v1.36.6
    include_imports: true
    include_wkt: true
    out: gen
    opt: paths=source_relative

今回はremoteプラグインを使用してコード生成を行いました。
以下から、参照できます。
https://buf.build/plugins/go

まとめ

共通のprotobuf定義を切り出して再利用する方法を簡潔に書いている記事があって欲しかったなと思ったので、その時の悩みを解決するために書いてみました。

うまく同じ悩みの方が、検索をかけた時にヒットするといいなと思います😊!

株式会社BALEEN STUDIO

Discussion