[DX Criteria] API駆動開発を試した話

2020-12-07

はじめに

CTOA Advent Calendar 2020の12/7の記事になります。

せっかくなので日本CTO協会に関わりあるものの話をしていきます。

自分が所属する日本CTO協会ではDX Criteriaという、より良いDX(二つの意味があるよ)のための基準を作っています。

その中の基準の一つにAPI駆動開発というのがあります。

DX-SDD

今年1年API駆動開発を会社として進めたので、そこで得た知見をご紹介します。

今年やったこと

会社としてモノリシックなアプリケーションだったものをプラットフォームな構成(マイクロサービスではない)に変更しました。

アーキテクチャー遷移簡略図

上記は簡略図で詳細は先日会社のブログに書いたのでそちらをみていただきたいです。

それに伴って新規のエンドポイントは内部サービス間のやりとりは基本的にgRPC,画面向けのやりとりはTwirp,GraphQL,OpenAPIなどを使うようにしていきました。 またフロントエンドは基本的にReact+TypeScript,サーバーサイドはGoという構成でやっています。

gRPC

Protobuf fileを元にGoのserverの実装とclientの実装をgeneateできます。

Protobuf fileのFormatterについてはこちらの記事を参考にclang-formatを使っています。

localでServerの動作を確認する際はBloomRPCというGUI Clientを用いて動作確認を行っています。

editor-preview (https://github.com/uw-labs/bloomrpc)

上記のようにProtobuf fileを指定すると定義されたサービスが表示され、選択し実行することで簡単にアクセスすることが可能になっています。

Twirp

gRPCと似ていてProtobuf fileを元にするプロトコル。gRPC-Webを利用する場合と異なり、HTTP/2だけでなくHTTP/1.1に対応しているため、対応ブラウザなどその辺りのことを気にしなくてよくなっています。

認証・認可APIは元々API GatewayからgRPCでアクセスされていたので、それに合わせてWeb向けのProtobuf fileを書けば諸々Generateできるしめちゃくちゃいいじゃんってなって導入した記憶。 使ったライブラリはサーバーフロントエンドはこちらのライブラリーを使用しました。

結論からいうと採択したのは失敗したと少し思っています。

サーバー側の実装は特別苦労しなかった記憶だが、TypeScriptのgenerateするちょうどいい実装がなくちゃんと動くまでに時間がかかってしまった。具体的にいうとIEで動かなかったり,SDKをStencilを利用してWebComonentを使っていたが、内部のRollupの処理で上手くいかず大変でした。

思想は好きなので時間があったら周辺環境を整えていきたいと思っています。

GraphQL

Server側のコードのgenerateはgqlgen,Client側のコードのgenerateはgraphql-codegenで行っている。

導入前や検証前はGraphQLはClient側にとっては夢のようなインターフェースだが、Server側はN+1が頻繁に起き,辛いのではと思っていたがdataloaderという仕組みを使うことで軽減させることができるようでした。

またClient側でTypeScriptで利用する上で、予め叩くQueryやMutation(Update文のようなもの)を書いておき、それをGenerateする際に読み込ませることによってそのQueryごとの関数と戻り値の型をよしなに作ってくれる。

それにより元にしたSchemaが正しくさえあれば型安全な世界で開発できるので幸せになりました。

OpenAPI

SimpleなRESTfulなAPIを作りたい時はOpenAPIを使っています。

Server側のコードのgenerateはoapi-codegen,Client側のコードのgenerateはopenapi-generatortypescript-axiosで行っている。

またSchemaのEditorとしてStoplight studioを利用しています。

public-api Studio Stoplight と Stoplight Studio OpenAPI Design Planning Modeling Tool

gRPCやGraphQLのSchemaファイルと比較するとJSONまたはyaml形式でDocumentの要素も強く定義が多く手動で書くのがめんどくさいため、GUIベースで入力すべきところがわかるので良いです。

またoapi-codegenはinteger型のgenerate結果が必ずInt型になってしまっていたが、優秀な同僚がPRを出してくれたためuint64でも使えるようになりました。

番外編

最近興味があるがProductionでまだ利用できていないものの紹介

sqlc

ちょっとAPI駆動開発から外れてしまうがSchema駆動開発近いものだと思っているsqlcを紹介します。

ORMapperの代わりになるようなものです。

使い方は下記のように予め利用するQueryを記載し、

-- name: GetAuthor :one
SELECT * FROM authors
WHERE id = $1 LIMIT 1;

そのSQLファイルを元にGenerateを行うと

fetchedAuthor, err := db.GetAuthor(ctx, insertedAuthor.ID)
if err != nil {
        return err
}

のような関数が自動で生成され、DBからデータを型安全に利用することができます。

SQLはいろんなところでいろんな呼び方がされやすく管理がしにくいがSQLファイルにまとまることで、Queryの質が担保されやすくなるのではと考えています。

まとめ

ここ1年API駆動開発に取り組んできて何が変わったかというと、サーバーサイドエンジニアとフロントエンジニアのやりとりやプロダクトを跨いだサーバーサイドエンジニアのやりとりがSchemaを返すことによって定義がはっきりし認識の齟齬が減りました。

簡単にMockを生成することができるため、サーバー側の実装を待たずにクライアントの実装がしやすくなりました。

API駆動開発をしない世界だとクライアントの実装するために、サーバーの実装を読むみたいなことをしなくてはならなくことも0ではなかったのでそれが間違いなくなくなります。

今回はAPI駆動開発のみに関して深く話したが、DX CriteriaはこのようなDigital TransformationやDeveloper eXperienceを良くするのための基準が設けられています。 DX Criteriaのはじめ方については3日目のアドベントカレンダーのNAVITIME_Techさんの記事を参考にはじめていただけたら良さそうです。

最後に

今日で30歳になりました。お祝いコメントお待ちしています。

会社でもアドベントカレンダーをやっているのでそちらも是非お願いします。

明日のCTOA Advent Calendar 2020はIwarkさんの記事になります。

ISUCON10の予選で惨敗した話 >>
@yudppp
Web engineer.