ここ最近Bufについてずっと調べていたまとめをZenn本にしました。
ここではやった感想的なものをまさかり気にせず書いておこうと思います。
Buf学んだモチベーション
直近でgRPC開発のプロダクトに入りそうだったのと何かどっかでBufという単語を見かけた気がしたので素振り的なノリで始めた。
Connectとか一応知ってはいたけどBufについてやBuf CLIとかは今回初めて知った。
調べていくうちにけっこうprotocから乗り換えました記事が出てきて、ざっくり見てるとかなり便利そう。ということで公式ドキュメント一通り読んでみることにした。
そもそも、Protobufやprotoc、gRPCといった用語について曖昧な理解だったり、gRPC-webやgRPC-gatewayといったConnect前からwebブラウザでgRPC通信するような技術についてほとんど知識がなかったのであわせてちゃんと理解しておこうというのがモチベーション。
gRPCサーバーの開発1年くらいやってたのだけど、雰囲気でgRPCやってたことが今回わかった。
Buf CLIについて
Buf CLIが提供するbuf lint, buf format, buf breakingが開発体験良すぎた。
そもそもLinterについては使ってなくていくつかProtobufプラグインとしてLinterが存在してることも今回初めて知った。個人的にはLintルールを細かく調整したりするのは好きじゃなくてデフォルトルールでいい感じに警告出して欲しい。Buf lintはBufがそれなりに厳格なルールをデフォルトで用意してくれているのでとりあえずそれに従うだけでいい。VSCode拡張を入れておけばコマンド実行する必要もなくすぐさまルール違反してないかわかる。ほんとこれくらいがいい。ただ、ルールは厳格なほうで、特にパッケージ名はルール厳守しないと警告がなくならない。
Formatはclang-formatが使えると聞いて使ってて、特に不満もなかったけどBuf CLIでできるなら全然そっちのがいい。フォーマットのルールに特にこだわりないし。VSCodeのAuto Formatが有効になればなんでもいい。clang-formatは各開発者がインストールしておく必要があるし、設定ファイルも必要なのがめんどくさい。
破壊的変更の検知はBuf CLIが提供する機能でこれを検知できるのはかなりいいなと思った。1年くらいスキーマ駆動やった感想としてはProtobufファイルを開発していくなかで頻繁に変更することになる。追加ならまだいいけど名称の変更や削除はクライアントが生成しているコードが変わるため、ビルドできなくなる可能性が高い。そのため、クライアントに「これ使ってますか...?次のマージで消してもいいですか..?」みたいな確認をすることになりかな変更のハードルがかなり高くなる。Buf CLIでそれが解決するわけではないけど破壊的変更があるのかないのかを気にせず、そして検知できるのは開発者目線では精神衛生上よい。
あとはコード生成。言われてみればそうだけどprotocを使ったコード生成のコマンドはオプションフラグの指定などが多くなりがちで覚えてられない。なのでシェルスクリプトを用意していた。Makefileを使ってる人も多いよう。で、Buf CLIはこういった複雑なプラグインの指定やオプションフラグの指定を外部の設定ファイルに切り出せる。このyamlファイルに宣言的に書いていく感じは今どきな感じがした。
そもそも、protocやprotocプラグインについての知識がなさすぎた。GoでgRPCのコードを生成するときにprotoc-gen-goをインストールしていたけどとりあえず必要らしいくらいの理解しかなかった。これがprotocプラグインでprotocのオプションとして指定することでGoのコードを生成しているということも知らなかった。わたしは雰囲気でgRPCをやっていた
protocについての理解を深めるのに以下の記事を読んだ。
この記事昔に読んでたっぽいけどほとんど理解できてなかった。今回じっくり読んでなんとなく理解できたと思う。どうやら成長はしているようだ
というか、この方のProtobufの記事がいくつかあるのだけど詳細度がエグいからProtobufやる人は全員読んだほうがいい。
Buf Schema Registry(BSR)について
Protobufのレジストリサービス。Docker Hubみたいなやつ。
これは今回初めて知ったのだけど、BSRがあることでProtobufの扱いが今までと大きく変わる。黒船来航くらい変わる
protocのプラグインをローカルに用意する必要がなくなるリモートプラグインという機能はBSRによって提供される。これ大事。何だかよくわからないモジュールのインストールをしなくて良くなる。チーム開発であれば開発ドキュメントにその旨を記載する必要がなくなる。そして、プラグインのバージョン管理まで実現するので「わたしのマシンでは動かない」といった状態になりづらい。
さらに、やばいのがBSRにProtobufモジュールを公開すると同時にnpmやGoモジュールなど各言語のモジュール管理の仕組みにProtobufから生成したSDKを公開する。公開さえしてくれていればgo getできるということだ。なんてこった。コードの生成すらしなくてよくなった。生成コードをGitHubの管理に含めるか、含めないで都度コード生成するかで悩む必要もなくなった。ということは、protoのリポジトリをサブモジュールとして組み込む必要もないということだ。
ただ、その分このProtobuf のモジュールの扱いが難しいと感じた。そもそも、モジュール名とかソースのディレクトリ構造とかパッケージ名とかちゃんと理解してやらないとLintの警告消えなくてハマる。
モジュールが公開できたとして、チーム開発でどのように運用していくかがちゃんと考える必要ありそう。そもそも、protoリポジトリのブランチをどう管理するのか。BSRもGitHubと同じようにブランチやタグ管理できるようにはなってるけどそれをどう連動させるか。ここらへんGitHub ActionsのようなCI/CD環境を構築もする必要があるし。まだ開発中でdevelopブランチでmainブランチにはマージしていないとき。BSRに公開しているモジュールもmainブランチとdevelopブランチでそれぞれ対応していてほしい。そうすると、本番環境への影響を考えずに開発ができる。
ただ、それを実現するのはまだ現状めんどくさそうなのでprotoリポジトリはmainブランチ一本で管理できると楽な気がしなくもない。
とりあえず、BSRの採用でProtobufのチーム開発の仕方は大きく変わる。
あと、ドキュメントの機能がでかい。今までprotoc-gen-docというプラグインを使ってドキュメントを生成しGithub PagesとかREADMEで公開していたけどいかんせん見づらい。チーム内でドキュメントあるよーって周知してたけどほとんど見られてなかった気がする。悲しい
BSRで公開したモジュールはそれ自体がドキュメントの機能も兼ね、見やすいUIを提供してくれるのでそれが嬉しい。もうやぼったいprotoc-gen-docによるドキュメントは生成しなくていい。
Connectについて
gRPCについての学習がメインだったので一応Connectはおまけ。ただ、webブラウザとgRPC通信が可能になる技術というのは非常に興味深い技術だと思っている。
しかし、現在webフロントエンドが採用できるサーバーとの通信手段は多くある。OpenAPIによるスキーマ駆動のREST API、GraphQL、tRPCやHono(たしかRPCモードがあるって聞いた)などなど。ここにConnectが加わったとしてGraphQLなどに勝てるだろうか?
あんまりフロントエンドのことは詳しくないけれどGraphQLとかのほうが嬉しいんじゃないだろうか。OpenAPIによるスキーマ駆動とConnectによるスキーマ駆動は完全に競合の関係でOpenAPIにするかConnectにするかといった話にはなりそう。
とか思ってたらProtobufのGraphQLみたいなの作ってた。
ぜんぜん中身見てないけどもしこれが実用できるようになったらwebとの通信手段にGraphQLと対立する通信方法になり得る。
まあ、実際はパフォーマンス的な話とか開発体験的な話もあるだろうし、こんなサーバー側がProtobufファイルでAPI設計したいだけの技術はあんまり流行らなそうな気はする。ただ、サーバー側主導でOpenAPIのようなスキーマ駆動の開発がしたいのであればConnectはかなり候補に上がってくる気がする。
おわりに
ということで思ってたよりもボリューミーだった。BufがProtobufを使ったスキーマ駆動を相当気に入っており、現状の課題、微妙なところを片っ端から整えていった感じがする、知らんけど。ドキュメント読んでるだけでProtobufへの情熱が伝わってくる。
確かに、Protobufを使用したスキーマ駆動開発はかなり体験が良かった。開発してるときはあんまり気にならなかったけどこんなに多くの課題を抱えている中で開発してたのかと思う。
Buf CLI、BSR、Connectを使うことでかなり体験の良いスキーマ駆動開発ができるのではないかと思う。ただ、BSRの運用やConnectあたりはまだ採用例も少なそうだし実際のプロダクトに採用するにはまだ勇気がいるかもしれない。
とりあえず、次gRPCを使ったチーム開発をする時はBufの使用を進言してみようと思う。