前までWebエンジニアとしてWebアプリケーションを作っていましたが、
最近iosのアプリを色々調べながら開発しています。
その中で、Webとアプリでこういう仕組みが違うんだなとか、どうやってデータベースに保存するのかなど、
色々経験してわかったことをちょっと備忘録的にまとめようかなと思います。
アプリ開発とWeb開発の違いということですが、
開発の仕方というよりは主にここではWebとアプリのそれぞれでプログラム構成であったり、仕組みの違いとかを話していこうと思います。
Webとアプリの違い
Webはステートレス通信
つまり、毎回Webにアクセスするとサーバが必要ファイルを
クライアントに渡して、ブラウザによって表示される。
つまりクライアントには開くファイルは持っていないので、
毎回サーバに問い合わせをしてファイルをいただきそのファイルの画面を表示するわけである。
しかしアプリは
よく皆さんのやるインストール
つまり、画面についてはアプリ内にインストールされるわけである。
なので、Webでは画面が変わる(アクセスするとかリンクを踏むとか)たびに通信が走り画面用のファイルをサーバからもらうわけだが、
アプリはすでに画面についてはクライアントサイドに入っている状態になる。
なのでWebの場合は毎回データと画面構築ファイルをサーバからいただくが、
アプリはデータだけをサーバからいただく形になる。
アプリはじゃあデータはどこからいただくのか?
それは当然サーバからいただくのはもちろん、デバイスにデータを保存してデバイスからデータを取得して表示するという方法もできます。
サーバからいただく場合はネットワークにつながっているときにサーバからデータをとって来て表示するのに対し、
デバイスに保存しているデータは、ネットワークに繋がっていなくても当然取得できるので、表示できる。
よく皆さんが利用するLineというアプリ。
Lineではアプリを起動するとメッセージが表示されるが、これはネットワークがつながっていてサーバからとってきて表示しているものもあるが、
ネットワークを切った状態でアプリを起動してみてください。
アプリ普通に起動でき、メッセージが表示されます。これは過去のメッセージのやり取りはデバイスに保存されていて、そこからとってきて表示しているわけです。
なのでネットワークにつながっていなくてもアプリが動かせるのはそのような特徴を持っています。
Webは毎回サーバに問い合わせて、画面構築ファイルやデータを取得するので、ネットワークをつながっていない状態でアクセスすると、
アクセスできませんとかネットワークにつながっていませんというエラーが表示されます。
アプリ開発のデータ保存方法
アプリのデータ保存ですが、
項目 | 説明 |
---|---|
1.サーバ側でのデータ保存方法 |
FirestoreやRealtime Database、APIを通じたMySQLなどのDBサーバ。 ※ FirestoreやRealtime Databaseであればトリガーを用いて通信するWebSocket(HTTPのアップグレード版)によって、リアルタイム通信が可能で、メッセージを送るとそれをサーバが送り先に自動的に送信する。MySQLではそのような機能はないので、自分で双方向通信を実装する必要がある。 |
2.RealmやCore Dataなどによるデバイスへのデータ保存 | ※ 何でもかんでもデバイスに保存するべきではなく、スマホの容量を圧迫してしまうため画像ではなくテキストデータなどの保存に向いている。スマホの容量が多いと電気消費量も増えたりメモリを食うため処理速度の低下の恐れがあるため、ユーザーからすると良くないアプリ認定。 |
など、アプリの性能や用途に応じてどういう保存方法がベストかを考える必要がある。
メッセージなどのリアルタイム性を求められるようなデータ処理の場合は、Firestoreは自分のメッセージ送信先のデバイスがアプリを起動していれば画面にメッセージを反映してくれるなどができるので、Firestoreを用いて実装するべきだし、過去のデータであったりあまり変わらないデータについては、
デバイスに保存するような処理にするなど、
ハイブリットなデータ保存方法をしっかりと考えた上で構築しないと不明な膨大なコストを招きかねないので注意。
Webに詳しい方であれば、
サーバサイドプログラムでPHPならPDOライブラリでmysqlに接続して、データベースに保存したり取得したりすることができるのはわかると思います。
なのでこれを利用して、APIサーバでそのようなmysqlに保存するような処理して、レスポンス処理をし、
アプリ側からそのAPIサーバにリクエスト処理しつつGET通信ならパラメータに、POST通信ならjson(ペイロード)で保存したいデータをAPIサーバにおくりサーバサイドの処理実行して保存するような処理の構築を行うことができる。
ただmysqlには接続している他ユーザーにも更新処理などの機能はないので、チャットなどリアルタイム性のものには適しません。そのためそういう場合はリアルタイムで双方向通信可能なWebsocketの仕組みを利用したFirestoreなどを用いるべきです。
スクリーンの読み込み
Webでは、毎回アクセスするたびに最新のデータを取ってきて実行して画面を表示するが、
アプリの場合は、一回スクリーンを表示すると再度そのスクリーンを表示しても再度プログラムを実行して画面の再構築をしてくれない。
つまりアプリ起動して1回きりしかコードを読み込んで画面を作ってくれない。
なのでデータが最新になったとしても、それを取得しにいくコードを実行してくれないため、更新されない。
SwiftUIではBindingという機能で、特定の値が更新されたら画面を再構築(再実行)してくれる機能がある。
すでにアプリにはクライアントサイドのプログラムがインストールされているわけで、
起動するとプログラムが全て動く
しかしそのあと値が更新されて一部の画面でその値を使っていたら新しい値に変更して表示してほしいわけだが、
すでにプログラムが動いてしまっているので、更新処理がかからない。
なので値が変わったら、画面のプログラムを再度構築処理をしてほしいという依頼をする必要がある。
それがバインディングという機能です。
@Stateや@ObservedObject、@EnvironmentObjectなど様々ある。
値の更新という観点では、
項目 | 特徴 |
---|---|
Web | 毎回画面遷移するたびにサーバからクライアントサイドのプログラムに最新のDBの値を乗せて、送ってくれるので最新データを見ることができる |
App | 画面遷移しても起動した時にアプリのプログラムが動いてその時点での値で表示される。 で画面遷移してもプログラムが再度走るわけではないので、更新もされない。 なのでバインディングという機能を用いて再度プログラムを動かす設定をしてあげる必要がある。 |
という違いがあります。