はじめに
この記事はドワンゴ Advent Calendar 2019の8日目の記事です。
自己紹介
ニコニコ動画とNicoBoxのサーバーサイドの開発をしています。最近はAPIサーバーを新しく作ったり、保守したりしています。
NicoBoxは、ニコニコ動画にアップロードされた動画のうち、ボカロや歌ってみたなどの音楽を聴くのに特化したアプリです。ボカロや歌ってみたを聴くのであれば非常に良いアプリなので、知らなかった人は使ってみてください。
(ゆるふわ)RESTの採用理由
GraphQLを採用したいけど大変そうだからRESTにしとくか 、と判断しました。
近年GraphQLが非常に流行っています。確かにGraphQLは我々にとっても非常に魅力的なものでしたが、導入するにはコストが高いと感じました。
RESTであれば、既存のコードが使えることが想像できますし、APIを利用するクライアントも使い慣れています。
便利な新しい技術の採用も重要ですが、今回はとにかく 低コスト で 早く リリースしたかったのです。
実際には厳密なRESTではなく、 RESTっぽい何か です。完全にリソース指向ではなく、search
, recommend
のような、リソースではないPathも存在しているゆるふわなRESTです。
OpenAPIを採用した理由
Confluence を使っていた
これまではAPIのドキュメント管理に、Confluence *1 を使っていました。
しかし、ConfluenceでAPIドキュメントを書くのは苦痛でした。表を作って、リクエストパラメータ書く程度であれば良いのですが、レスポンスを書くのが特に辛いです。階層構造があるので表では表現しづらいですし、サンプルレスポンスのJSONを手で書くしか無いので辛すぎました。
OpenAPIを使おう
OpenAPI は YAML 形式でAPIの定義を書くと、自動でドキュメントを生成してくれます。このドキュメントが非常に見やすいです。サンプルレスポンスも簡単にかけます。
OpenAPIとは
OpenAPI について詳しくは説明しません。OpenAPIについて知りたい人は、この記事を読むとイメージが湧くと思います。
とにかく、APIドキュメントが書くのが大変だったので、OpenAPIを採用した、というのが最初でした。
OpenAPI の運用方法
リポジトリ
OpenAPI の yaml ファイルと、 ソースコード を同じリポジトリで管理するようにしています。リポジトリが別れていると
- あっち行ってコミット、こっち行ってプルリクマージ、 行ったり来たりがだるい *2
- コード変更したけどドキュメントだけ忘れてる 、みたいなことに気づきづらい
ためです。
ディレクトリ構造
ドキュメントはGitHub Pagesを使って公開します。GitHub Pagesは、masterの docs
ディレクトリ以下を GitHub Pages として公開する設定があるので、これを活用します。
リポジトリのルートには、docs
ディレクトリがあり、ソースコード用のディレクトリがあったりします。docs
ディレクトリ以下はこのようになっています。
specs
ディレクトリ以下に OpenAPI の YAML が入っています。specs
以下にはindex.yml
が入っていて、これが OpenAPI の YAML です。index.html
は、ReDoc という、OpenAPI の YAML を元にAPIドキュメントを生成してくれるやつです。GitHub Pagesでこのindex.html
にアクセスすると、specディレクトリ以下にあるYAMLを読み込んで、APIドキュメントを表示してくれます。
コントリビュートとCI
package.json
は以下のようになっています。
{ "scripts": { "watch": "http-server --cors -c-1", "validate": "swagger-cli validate ./specs/index.yml" }, "dependencies": { "swagger-cli": "^2.3.0" }, "devDependencies": { "http-server": "^0.11.1" } }
npm run watch
を実行するとHTTPサーバーが立ち上がります。手元のPCでYAMLをいじる時に、index.html
でAPIドキュメントの生成結果を確認しながら編集できます。npm validate
は YAML ファイルが正しく書かれているかをチェックするコマンドです。ブランチをpushするとCIでこのコマンドが実行され、書き方が間違っている時はCIが落ちます。
OpenAPI を採用してよかった点
慣れればすごく良い
慣れればすぐ書けるようになります。修正も簡単です。表を頑張って組み直したり、サンプルレスポンスを頑張って書き直したりする必要はありません。
Code Generator が使える
OpenAPI には Code Generator というものがあり、YAMLからAPIクライアントのコードを自動生成できます。
はじめは Code Generator を利用する予定はなかったのですが、今ではガッツリCode Generatorを使っています。
OpenAPI の辛い点
正確に書こうとするとかなり大変
APIドキュメントの生成程度であれば、多少適当に書いてても動きます。
しかし、Code Generator やその他の周辺ツールを活かそうとすると、かなり厳密に書く必要があります。厳密に書けるようになるまではそこそこ学習コストがかかります。
ツールの質が微妙な時がある
我々は openapi-generator という Code Generator を使っているのですが、生成されるコードの質が微妙なことがあります。
何回か openapi-generator にプルリクを送ることになりました。
dreddというツールも使いたいのですが、OpenAPI Version 3 には完全対応していません。*3 dreddはYAMLを読み込み、APIを叩いてテストしてくれるツールです。
YAMLが巨大になると辛い
APIの数が増えてくるとYAMLファイルが巨大になります。しかし、これを分割するGoodな方法がありません。仕方ないので自分たちでなにかツールを作る予定です。
本当の意味でRESTになっていないと辛い
例えば、/recommend/video-and-playlist
を叩くと「動画」と「プレイリスト」が混ざって返ってくるAPIがあるかもしれません。*4 このような真のRESTでないAPIを書こうとすると非常に辛いです。
なんとかドキュメントまでは生成できるのですが、Code Generator が対応していません。
OpenAPIに頼らないか、APIを真のリソース指向にする必要がありそうです。
ネットに知見があまり無い(気がする)
僕が日本で一番本気でOpenAPIの運用について考えている、、、かどうかはわかりませんが、我々の規模でOpenAPIを運用しているところはあまり無い気がしています。
少なくとも、僕が導入した2017年頃、ググっても何も知見が出てきませんでした。今調べたら結構出てきますね。2019年の記事が多そうです。
ちなみに、2017年の導入当時にはこの記事を参考にしました。
まとめ
- RESTを採用するのがコストが低いのでRESTを採用した
- APIドキュメントを書くのが辛いのでOpenAPIを導入した
- APIドキュメントを書くだけならそんなに難しくないし便利
- Code Generator などの周辺ツール使おうとすると結構学習コストがかかるし、たまに微妙なツールもある
総合的には導入してよかったです。導入しないメリットはほぼ無いかと思います。