本セッションのテーマは、ネイティブによるスマートフォンアプリケーションの開発における注意点、設計時のポイント、工夫した点など。前半に堀田敏史氏がサーバサイド、後半に白倉悠祐氏がクライアントサイドの開発について語るという構成で行われた。
サーバサイドからみたネイティブアプリ開発のポイント
両氏が所属するチームが開発しているのは、女性向けの箱庭系ゲームだ。ゲームで中心となるフローは、『ショップで植物のタネを購入』『場所を選んでタネをまく』『発育を待つ』、というものになる。では、同様の機能を従来のモバイルアプリと、ネイティブアプリに盛り込む場合ではどのような違いがあるのか。
まず、通信のタイミングが違う。Webアプリでは、ユーザの操作によりページをリプレースするごとに、1回通信が入る遷移になっている。対してネイティブでは、必ずしも1タップ=1通信ではない。フローベースで、UI、画面遷移に応じて、必要に応じたタイミングで通信が行われる。
もう一つの違いは、表示データの管理場所だ。Webアプリでは通信のたびにすべてのデータをサーバから配信するが、ネイティブアプリでは、更新頻度の低いデータなどをローカルに置くことができる。以上の違いを念頭に堀田氏は、ネイティブアプリのサーバサイド開発において、通信のタイミングとデータの管理方法、APIの3点を考えることになった。
通信のタイミング
1点目、『通信のタイミング』だが、ネイティブアプリであっても、例えば各アクションのタイミングで都度通信をはさむ手法も選択肢の一つとなる。この手法では、サーバ側と常に同期しているため、データ不都合の懸念を少なくできる。しかしネイティブの特徴である、クライアントでのパフォーマンスなどが、通信のタイミングでブロックされてしまう。
都度通信の反対、つまりすべて非同期で通信する手法もある。一定間隔など、ある特定のタイミングで同期する。この方式では、ユーザのアクションがブロックされないので、ユーザ体験向上に寄与できる。一方、サーバ側と常に同期していないため、注意が必要だ。例えばサーバ側でショップのリストがリプレースされたとき、ユーザ側がそのタイミングで通信しているとは限らない。またサーバ側で知り得ない、ユーザのアクションログを管理する必要がある。
さらに第3の選択肢として、更新タイミングなどで適宜同期するタイプが考えられる。例えばメニュー操作など、データの更新がない時点では、通信を行わない。タネまきを行うなど、データの更新が行われるタイミングで通信する。この手法であれば、データ不整合の懸念は少ない。ただ、都度通信よりは軽微だが、通信のタイミングでユーザ側のアクションがブロックされる。
それぞれの通信パターンには一長一短がある。堀田氏は「ネイティブ開発の場合、UIのフローやアクションのタイミングに合わせた最適な通信のタイミングを、最初の段階で考えることが重要になる」と語る。
データの管理方法が変わる
2点目の『データの管理方法が変わる』は、一部のデータをローカルに置いておけるようになったことが背景だ。そこで更新頻度の少ない、ゲームでいえば初回で取得してしまって、変更があったときのみダウンロードする形で開発されている。一方、更新頻度が高いデータはユーザの操作に合わせて適宜同期する。
具体的には、サーバが最初に通信するとき、マスタテーブルのハッシュリストのようなものを取得し、基本的に初回に関しては一括でダウンロードする。2回目以降は、テーブルやハッシュを比較し、変更があったテーブルのみサーバにリクエストし、ダウンロードする仕組みが入れられている。
アセット管理も、基本的には更新頻度で行う。ただしマスタデータと比較すると、容量などが大きいため、ユーザのプレイ進捗により初回ダウンロード量をコントロールできるように考えられている。また、アセット単位でのバージョンの管理が必要で、通信のタイミングでチェックし、更新があればアップデートする形で行われている。
設計した通信タイミングで呼ばれるサーバサイドAPI
3点目、『設計した通信タイミングで呼ばれるサーバサイドAPI』では、データフォーマットに関してはJSONが使われている。また、クライアント側の開発者から見えやすいように、ビューワが開発された。
また、APIがクライアントから呼ばれてエラーが生じると、その結果に応じてクライアント側のUIの表示が変わってしまうことがある。そこでインターフェースやエラーコードの、クライアントとの擦り合わせが特に重要となってくる。
今回のサーバサイド開発で使われている要素技術は、基本的にはWebと変わらない。例えばPHP 5.3、Ethena 2.6でWeb APIのサーバサイドロジックを作り、Mysql 5.5で永続データを保存し、必要に応じてShardingしていたりしている。また、永続データで参照と更新頻度の高いデータ保存に関してはFlareを使用し、一時的なキャッシュデータ保存に関してはMemcachedという形で構成し、作っている。