25 ポイント 投稿者 disjukr 2022-04-06 | 9件のコメント | WhatsAppで共有

サンタTOEICを提供しているRiiidでは、gRPC/Protobufを非常に活発に利用しています。
私がRiiidに入社して間もない頃、今後バックエンドチームがフロントエンド(モバイル/ウェブ)に提供するすべてのAPIはgRPCに統一する、という方針が共有されました。

ウェブフロントエンドでgRPC/Protobufスタックを使うには、従来はprotocにJS/TSプラグインを組み合わせて使うか、Protobuf.jsを利用する方法がありました。

protocの公式JSプラグインには、非常に古いスタイルのコードを生成してしまう問題があり、エコシステムの各種プラグインも私たちの要件をすべて満たしてはいませんでした。ネイティブバイナリ(protoc)への依存がついて回る不便さもありました。(最近ではM1マシンでprotocをインストールしづらい問題もあります。)

私たちはこれまでProtobuf.jsを使ってさまざまな製品を作ってきましたが、社内で作られるすべての製品において、プラットフォーム間でやり取りするあらゆるインターフェースをProtobufで扱うようになると、Protobuf.jsは私たちが必要とする水準まで成熟していないことが分かりました。
メッセージ名が同じだと別の名前空間にあるメッセージと誤認したり、グローバル名前空間でenumの後にメッセージ宣言が続くとメッセージ型コードが生成されなかったり、TypeScriptの型定義が生成されたJSの動作と一致しなかったりと、さまざまな問題に遭遇しました。

この過程で、特定の製品に必要なprotobufスキーマだけを抽出してビルドする仕組みを構築するために、pollapoというprotobufパッケージマネージャーを作りました。
(当時も他のprotobuf依存関係マネージャーはありましたが、バグがあったり、ネストした依存関係をサポートしていないといった問題がありました。また、bufが提供するパッケージ管理機能は当時まだ開発中で、ブログ記事があるだけの状態であり、私たちがpollapoを作って社内移行を完了するまで完成していませんでした。)

pollapoによって製品ごとにビルドするスキーマ数を大きく減らすことができ、同じメッセージ名などに起因するバグも減りましたが、それでもなおバグやビルドの問題は残っており、これを解決するためにprotobuf to typescriptコンパイラを自作しました。

サンタTOEICは現在、protobuf.jsを全面的に撤去し、pbkitへの置き換えを完了しています。


サンタTOEICを含め、Riiidで開発されるアプリはWebViewを積極的に利用しています。
WebViewは、端末/ユーザー情報や現在表示中のコンテンツ情報を取得するためにネイティブと通信しますが、その際のインターフェースもProtobufのサービススキーマで定義しています。

pbkitでは、サービスコード生成時にネットワークレイヤーをgRPCの代わりに別のプロトコルへ差し替えられるインターフェースを提供しています。
pbkitコンパイラを使うウェブフロントエンドエンジニアは、モバイルネイティブと通信する際に、それがgRPCリクエストなのか、モバイルエンジニアと取り決めたApp Bridgeプロトコルでの通信なのかを意識する必要がありません。

また、Chrome拡張も自社で開発したため、モバイルとの通信内容もChrome DevToolsのpbkitタブで、ネットワークタブを見るように手軽に確認できます。

protobufスキーマコンパイラを自作したことで、コードエディタ上でGo to Definitionのような機能もすぐに実装できると考え、VSCode拡張も作成しました。
従来のVSCode向けprotobuf拡張は、シンタックスハイライト程度の機能しか提供していませんでしたが、pbkit VSCode拡張には正しく動作するGo to Definition機能が入っています。

今後はswift/kotlin/pythonなど他言語対応、サーバーユースケース対応、ドキュメント生成ツール、リンティング/フォーマットツールなどを開発していく計画です。
これらのツールを一緒に開発するエンジニアも募集しています: https://riiid.com/ko/career/dx-software-engineer

ぜひご注目ください。

pbkitリポジトリ: https://github.com/pbkit/pbkit
VSCode拡張: https://marketplace.visualstudio.com/items?itemName=pbkit.vscode-pbkit
Chrome拡張: https://chrome.google.com/webstore/detail/pbkit-devtools/fjacmiijeihblfhobghceofniolonhca

9件のコメント

 
sixmen 2022-04-06

私たちの会社では数年前、gRPCと比較検討した末にThriftを選びました。ThriftもJSジェネレーターが不完全だったため独自に修正しましたが、やるべきことではないと痛感しました。なのでgRPCを選ぶべきだったのかと思いましたが、あちらも事情はあまり良くないようですね。

その後、私たちはGraphQLを選び、私は満足しています。たまに通信オーバーヘッドが気になることはありますが、バイナリベースのプロトコルはどうしても使う気になれませんでした。

 
cometkim 2022-04-06

ニンジンマーケットでとてもよく使っています!! ( _ _ )

社内APIメッシュ用にうまく活用しようと頑張っています(笑)

 
kbumsik 2022-04-06

おお、すごいです!

 
kbumsik 2022-04-06

ところで、会社ですでに本番運用で使える程度なら、v0.0.44 みたいな pre-alpha っぽいバージョンはもうやめてもいい気がします。

バージョン番号だけを見て使わない人もいそうですね…

 
winterjung 2022-04-06

わあ、コンパイラを直接作られたんですね。素晴らしいです! (golang のコードがどう生成されるのか気になっていたのですが、今のところは deno と node.js のみ対応しているようですね)私は protoc や buf に ts-proto などを組み合わせて使ったりするのですが、ts-proto と比べて生成される ts コードにどんな違いがあるのか気になります。

 
bichi 2022-04-06

なんだか遠回りしている感じですね https://github.com/trpc/trpc

 
danchu 2022-04-06

bichi さん / サーバー API が gRPC プロトコルで提供される場合、trcp はそれをサポートするためのものではないのではないでしょうか〜?

 
disjukr 2022-04-06

gRPC/Protobuf スタックを使うのが理想的ではない、という点には同意します。(自分が望んで使ったわけではなく、会社の事情で使っていたので)
ただ、trpc は zod を使ってインターフェースを定義するため、すべてのプラットフォームで TypeScript を使う場合には理想的だと思います。
サーバーを Kotlin で書いている私たちの環境では使うのが難しそうですし、モバイルネイティブ(Swift、Kotlin)と通信する場合にも適していないように見えます。

 
xguru 2022-04-06

わあ、コードにVS/Chrome拡張まで……すごいですね!! 応援しています。
紹介文をとても上手く書いてくださっているので、ただRepoを訪れた人よりも、GeekNews経由で訪れた人のほうが、より多くの情報を得られそうです ^^;

現在Protobufを使っている方がコメントを残してくだされば、かなり参考になりそうです。