投稿日
UI開発にSwaggerで作ったmockサーバーを使う
もくじ
こんにちは。西日本テクノロジー&イノベーション室の藤田です。 日々(技術的に)強くなりたいと言っている新卒3年目です。 弊社では名刺を入社した時に100枚、それ以降も部門名称が変わるたびに100枚ずつ支給されるのですが、入社してからもらった名刺は400枚になりました。来年には500枚になっているかもしれません。
この記事では、先日まで関わっていたサービス開発案件で蓄積されたノウハウとして、Swaggerで生成したmockサーバーを使ってUI開発をする流れを書いていきます。
背景
3人チームで新規サービスを開発していました。
APIはRuby on Rails、UIはReactを使っており、私はUI開発者として参画しました。
今回の開発では、API開発を待たずともUIの開発ができるよう、Swaggerを使って生成したmockサーバーを使ってUI開発を行いました。
ここではSwaggerを使ってAPI仕様を定義し、API仕様からmockサーバーを生成してUI開発をする流れを共有します。
使ったもの
JSONまたはYAMLでAPI仕様を定義できます。プレビュー機能があり、構文間違いを都度チェックできるエディタです。オンラインのものもありますが、今回はDockerイメージを使用しました。 Swagger Codegen
API仕様を定義したYAMLファイルからmockサーバーを作ってくれます。こちらもDockerイメージを使用しました。
開発の流れ
1.DockerでSwagger Editorを立ち上げる
Docker Hubにイメージがあります。
今回はポート9200から繋げるように立ち上げました。
docker pull swaggerapi/swagger-editor
docker run -d -p 9200:8080 swaggerapi/swagger-editor
サンプルとしてSwagger PetStoreのAPI仕様が入っています。
2.API仕様を定義する
APIの開発者と認識を合わせながらAPI仕様を定義します。
先ほど立ち上げたSwagger Editorを使ってAPI仕様を書きます。今回はYAMLで書きました。
サンプルがエディタに入っているので、書き方が全くわからないということはありませんでしたが、細かいOpen APIの文法についてはOpenAPI Specificationを参照しました。
3.開発用mockサーバーを作成する
API仕様ができたら、開発用mockサーバーを作ります。mockサーバーの生成にはSwagger CodegenのDockerイメージを使いました。
カレントディレクトリにswagger.ymlを置いて、生成したmockサーバーを置くディレクトリmockを作った状態で以下のコマンドを叩くと、mockディレクトリ配下にmockサーバーが出力されるはずです。
docker run --rm -v `pwd`:/work swaggerapi/swagger-codegen-cli generate -l nodejs-server -i /work/swagger.yml -o /work/mock
UI開発にReactを使っているので、Reactが動く環境であれば特に手を加えることなく動かせるnodejs-serverを選びました。
サーバーポートはYAMLの host
で指定できます。以下のYAMLだと、mockサーバーがlocalhost:3000で起動します。
swagger: "2.0"
info:
title: "お菓子"
description: "お菓子を返すAPI"
version: 1.0.0
basePath: "/api"
tags:
- name: "item"
description: "商品"
host: localhost:3000
4.mockを動かして開発する
3で作ったmockサーバーを yarn install
yarn start
してUIの開発に着手します。
例えば商品IDを指定して商品の詳細情報が欲しい場合、Swaggerで以下の通り定義していたとします。
paths:
/items/{item_id}:
get:
tags:
- "item"
summary: "商品の詳細を返す"
produces:
- "application/json"
parameters:
- in: "path"
name: "item_id"
type: "integer"
required: true
responses:
200:
description: "リクエストが成功した場合"
schema:
$ref: "#/definitions/Item"
404:
description: "指定された商品が見つからない場合"
definitions:
Item:
description: "商品の詳細情報"
type: object
properties:
name:
type: "string"
description:
type: "string"
category:
type: "string"
price:
type: "integer"
description: "金額"
example:
name: "ブラックサンダー"
description: |-
みんな大好きブラックサンダーが装い改め新登場!
1994年の発売から20年以上愛されている「ブラックサンダー」が2003年のパッケージ変更から14年ぶりにフルリニューアル!
チョコレートとビスケットのバランスを見直し、カバーチョコレートを増量!
category: "チョコレート"
price: 30
React側で以下のようにAPIを叩くと、JSONが返ってくるはずです。
ちなみに、YAMLでitem_id
のtypeをinteger
と定義しているので、idにinteger以外を指定するとエラーになります。ただ、mockなので指定するidはintegerである限り何を指定しても同じJSONが返ってきます。
async getItem(id) {
const resp = await axios.get(`/api/items/${id}`)
return resp.data;
}
{
"name": "ブラックサンダー",
"description": "みんな大好きブラックサンダーが装い改め新登場!\n1994年の発売から20年以上愛されている「ブラックサンダー」が2003年のパッケージ変更から14年ぶりにフルリニューアル!\nチョコレートとビスケットのバランスを見直し、カバーチョコレートを増量!",
"category": "チョコレート",
"price": 30
}
JSONの中身は、YAMLでexampleに設定した値です。
exampleの設定方法は公式ドキュメントにある通り色々ありますが、今回はItem
というModelにexampleを定義しました。Modelでexampleを定義せず、個々のレスポンスにexampleを定義することも可能ですが、複数のAPIで同じModelのレスポンスが欲しい場合にexampleごとModelを使いまわせるよう、Modelにexampleを定義しています。
これで、API開発を待たずとも正常系を確認できる環境が整いました。
使ってみて感じたこと
良かった点
Swagger Editorが使いやすい Swagger Editorにはプレビュー機能がついているので、構文間違いがないか都度チェックできて便利でした。
また、プレビュー機能のおかげで、API仕様の共有を開発者間でスムーズにできました。
UI開発とAPI開発を独立して行えた
当初の目的が達成できました。mockの生成方法が簡単なので、特に手間取ることなくUI開発を進めることができました。
不便に感じた点
Swagger Editorで構文エラーが起きると入力補完が一切効かなくなる
入力補完がきかなくなるとだいぶしんどいです。
Modelにexampleを定義する場合、そのModelの配列は各要素に異なる値を使用できない
今回Modelにexampleを定義していますが、exampleは1つのModel定義につき1つしか定義できない制約があります。この制約によって、同じModelが要素となる配列に対して、異なるサンプル値を設定できません。
例えば、あるカテゴリの商品を取得するAPIがあったとします。このAPIは、ItemというModelから成るオブジェクトを要素とする配列を返します。
paths:
/categories/{category_id}/items:
get:
tags:
- "item"
summary: "あるカテゴリに属する商品一覧を返す"
produces:
- "application/json"
parameters:
- name: "category_id"
in: "path"
required: true
type: "integer"
responses:
200:
description: "成功時のレスポンス"
schema:
type: array
items:
$ref: '#/definitions/Item'
404:
description: "商品が見つからない場合"
Itemは次のように定義されています。
definitions:
Item:
description: "商品の詳細情報"
type: object
properties:
name:
type: "string"
description:
type: "string"
category:
type: "string"
price:
type: "integer"
description: "金額"
example:
name: "ブラックサンダー"
description: |-
みんな大好きブラックサンダーが装い改め新登場!
1994年の発売から20年以上愛されている「ブラックサンダー」が2003年のパッケージ変更から14年ぶりにフルリニューアル!
チョコレートとビスケットのバランスを見直し、カバーチョコレートを増量!
category: "チョコレート"
price: 30
1つのModel定義につき1つのexampleしか定義できないので、配列に入るサンプル値も1種類しかないことになります。上の例でいうと、/categories/:id/items
で返ってくる配列の要素にはブラックサンダーしかないことになります。
mockサーバーを作った目的はUI開発のためのデータ取得です。UI開発をしていたら、表示対象のデータを色々なもので試したくなるはずです。画像サイズ、縦横比、タイトルの文字数など、色々な種類のデータを入れて見た目を調整したくなります。
しかし、Modelに定義できるexampleは1種類なので、データは1種類しか扱えません。これはUI開発をするにあたり不便に感じました。
おわりに
Swaggerを使ってmockサーバーを生成してUI開発をした流れを書いてみました。
API仕様の共有が開発者間でスムーズにできた点、UI開発とAPI開発を独立して行える点は非常によかったです。 不便に感じた点はあるものの、mockが簡単に生成できる点はかなり魅力的なので、今後もUIとAPIを独立して開発したい時はSwaggerを使おうと思います。
本コンテンツはクリエイティブコモンズ(Creative Commons) 4.0 の「表示—継承」に準拠しています。