Edited at

gRPCのMock戦略


はじめに

API開発において、サーバとクライアントが別れて開発することは多いと思います。

しかし、そのような場合にクライアントが平行、あるいは先行して開発をすることになると、必要となるサーバが存在しないため開発がしにくくなります。

そこで出てくるのがAPIのモックサーバです。

Dev Mock

クライアント開発時、本物のサーバの代わりにモックサーバを利用し開発を行い、サーバの開発が完了した時点で結合を行うようにします。

ここではよくあるREST APIと比較したgRPCのMockについて記載します。


REST APIのモックサーバ

RESTのモックサーバはホスティングサービスから、単体のツールまで沢山あるので、ここではシンプルなjson-serverを例にしたいと思います。


json-serverによるモック

json-serverを利用した開発は簡単で、レスポンスとなるjsonを定義し、json-serverに読み込ませるだけです。


Terminal

> npm install -g json-server



db.json

{

"posts": [
{ "id": 1, "title": "json-server", "author": "typicode" }
],
"comments": [
{ "id": 1, "body": "some comment", "postId": 1 }
],
"profile": { "name": "typicode" }
}


Terminal

> json-server --watch db.json


また、CRUD処理やソート、ページングなどもjson-serverの仕組みに乗ることで利用が可能です。

クライアント開発では、事前にjsonの定義でサーバ相当の機能を実現、開発し、サーバ開発が完了した時点で本物のサーバを利用するようにします。


gRPCのモックサーバ


gRPCの開発スタイル

Kobito.XIS1od.png

gRPCにおける開発では概ね以下のフローで行います。


  1. クライアント/サーバ間のインターフェイス定義

  2. protocにより、クライアント/サーバの自動生成

  3. サーバ側の実装

  4. クライアントからサーバの利用

ここで重要なのが、2.クライアント/サーバの自動生成です。

言語依存はありますが、ここで生成されるサーバのコードはほぼそのままサーバとして実行が可能なコードが生成されます。

つまり、RESTでいうjson-serverのような仕組みが公式でサポートされています。

また、生成するサーバのコードも任意の言語で自動生成可能なので、クライアントを実装する開発者が扱いやすい言語のモックサーバで開発が可能です。

ということで、gRPCだと多くの場合、外部のMockツールがなくてもクライアントだけの開発が可能になります。


より簡単にgRPCのモックサーバを

gRPCの開発フローに乗ると、サーバ生成は簡単に行えるようになりますが、RESTのときと比べるとサーバ生成がちょっと手間に感じるかもしれません。

そんなときに便利なのが、Protobuf.jsのdynamic codegenです。

Protobuf.jsを使うとprotoファイルを直接読み込み、モック化したい処理の実装することで、1つのjsファイルだけでモックサーバが用意できます。

後は通常のnodeアプリケーションと同様起動するだけです。


server.js

// proto定義の読み込み

const PROTO_PATH = __dirname + '/../../protos/helloworld.proto'
const grpc = require('grpc')
const protoLoader = require('@grpc/proto-loader')
const packageDefinition = protoLoader.loadSync(/* ... */)
const hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld

// モック
function sayHello(call, callback) {
callback(null, {message: 'Hello ' + call.request.name})
}

// サーバの設定
function main() {
const server = new grpc.Server()
// モックの組み込み
server.addService(hello_proto.Greeter.service, {sayHello: sayHello})
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure())
server.start()
}

main()



Terminal

> node server.js


単純なnodeのスクリプトになっているので、固定値を返すモックだけでなく、動的な処理を埋め込むのにも便利です。


RESTとのgRPCのMock比較

簡単に比較すると以下の特徴があります。

REST
gRPC

機能
シンプルなものから高機能なものまで様々
用途に合わせて選択可能
本物のサーバと同様の機能を実現可能
使い慣れた言語でコントロール

拡張性
DSLや拡張機能、各種設定
使い慣れた言語で拡張できる

学習コスト
学習コストが低いものは機能や拡張性が低く、高機能だと学習コストが上がりやすい
gRPCサーバの基礎知識があればよい

保守性
APIの定義を保証する仕組みがないため、別ツールと組み合わせるか、テストなどを行う必要がある
スキーマ定義の仕組みが公式サポートのため、インターフェイスが保証されている

※ RESTのモックサーバはツールに依存します


まとめ

gRPCは提供されている仕組みそのものが、Mock機能も兼ねているのでその仕組みに乗るのが便利です!


参考