U-Lab ― ミニアプリを作成して公開するまで

このUブログは、書いた内容を全員に同じように見せる静的サイトです。ファイルを置いておけば動くので、仕組みがシンプルで壊れにくい。読み物を届けるにはこれで十分です。

ただ、静的サイトだけでは作れないものもあります。押すと結果が変わるボタン、他の人と共有できる記録、そういう「触ると動く」ものです。そこで、動くミニアプリを並べる実験場を別に作りました。名前は「U-Lab(ユーラボ)」。lab.ublogs.net で公開しています。

この記事では、U-Labをどういう考えで設計したのか、そして実際に作りながら戸惑った点や見つけた改善を記録します。

そもそも何を作ったのか

U-Labは「小さな動くアプリをたくさん並べる場所」です。占いのような遊びから、みんなで共有できる記録まで、思いついたものを1つずつ足していきます。

最初に作った実際のアプリは「Share My Color Days」。土日祝の空き予定を記録して、そのページを人に共有できるツールです。1人が編集して、URLを渡された人が閲覧する、という形にしました。

ここで大事にしたのは、アプリを1個ずつ丁寧に作ることより、「アプリを次々足せる土台」を先に作ることでした。Uブログで記事を1本足す手順を決めておいたのと同じ発想です。

設計の考え方1 ― サーバーが要るかどうかは「共有」と「秘密」で決まる

最初に整理したかったのが、どのアプリにサーバーが必要なのか、という点でした。

ここで「サーバー」という言葉を補っておきます。サーバーは、常に動いていて依頼に応えるコンピューターのことです。U-Labでは、依頼を受けて処理する部分に「Lambda(ラムダ)」、データをしまう部分に「DynamoDB(ダイナモDB)」というAWSの仕組みを使いました。AWSはインターネット越しにコンピューターの機能を借りるサービスです。

調べる前は「動くアプリ=サーバーが要る」と思い込んでいました。整理してみると、そうではありませんでした。占いや画面の演出のように、見る人のブラウザの中だけで完結する動きは、サーバーがなくても作れます。ブラウザに送られてきたプログラム(JavaScript)が、その場で計算して結果を出すからです。

サーバーが本当に必要になるのは、次の2つのときだけでした。

  • データを保存して、他の人とも共有したいとき
  • 見せたくない秘密を隠したいとき

この切り分けができると、簡単なアプリは簡単なまま、安く安全に作れます。そこでアプリを足す手順を、サーバー不要のものから始める形にしました。まずブラウザの中で完結するものから作り、必要になったらサーバーを足す。順番を決めておくと、いきなり複雑なものに手を出さずに済みます。

設計の考え方2 ― データを「誰と共有するか」で置き場が決まる

もう1つ、アプリを作る前に決めておくと楽になる軸がありました。「そのデータを誰と共有するか」です。3つに分けました。

  • 自分だけ ― データはそのブラウザの中に置く(保存先は端末のブラウザ)
  • URLを渡した人だけ ― サーバーに置いて、合言葉つきのURLで共有する
  • 全員 ― サーバーに置いて、誰でも見られるようにする

共有範囲が決まると、データの置き場が自動で決まります。自分だけならブラウザの中、それ以外はサーバー、という具合です。作る前にここを決めておくと、途中で「このデータどこに置くんだっけ」と悩まずに済みました。

「自分だけ」のデータには落とし穴もあります。ブラウザの中に置いたデータは、そのブラウザ・その端末でしか見られません。別のパソコンで開いたり、閲覧履歴を消したりすると消えてしまいます。これを黙っていると「データが消えた」と誤解される可能性があったため、画面にその注意を出すことにしました。

設計の考え方3 ― 手元は信用しない、守りはサーバーに置く

これが一番大きな気づきでした。

きっかけは、利用する人のアクセスの流れを追ったことです。ページを開くと、ブラウザはサーバーからHTMLや画面を動かすプログラム(JavaScript)を受け取ります。つまりプログラムは、見る側の手元にダウンロードされてきます。

ここで疑問が出ました。「手元に来るということは、そのプログラムの中身は全部見えてしまうのでは?」。その通りでした。ブラウザには開発者向けの機能があり、受け取ったプログラムを開いて中身を読めます。

これは謎解きアプリを考えたときに問題になりました。正解をプログラムの中に書いておくと、答えを読まれてしまいます。手元にあるものは、書き換えることもできます。そこで一本の線を引きました。

  • 手元(ブラウザ)で動くもの ― 見えるし、書き換えられる。信用しない
  • サーバーで動くもの ― 見えないし、触れない

守りたいこと、つまり正解の判定や、秘密の値そのものは、必ず見えないサーバー側に置く。これを出発点にすると、これまで迷っていた設計判断がすべて同じ考えで説明できました。謎解きの正解はサーバーに隠し、判定だけサーバーにやらせる。共有カレンダーでも、編集を許す「鍵」の照合はサーバーで行い、その鍵の値は閲覧する人には絶対に返さない。

ログインの仕組みを持たない匿名のサイトなので、「1人1回だけ」のような制限も完全には作れません。手元の記録は消せるからです。手元で行う制限は、あくまで普通に使う人向けの体験の調整であって、守りではない。本当の守りはサーバー側に置く、と割り切りました。

戸惑った点1 ― 「反映されたつもり」を疑う

ここからは、実際に手を動かして戸惑った点です。

共有カレンダーに名前を付けられるようにしたとき、名前の入力方法を途中で変えました。古い方式の名残がコードのどこかに残っていたのですが、直したつもりが実際には反映されていませんでした。

思い込みで進めず、ファイルを読み直して現状を確認したところ、一部の分岐にだけ古いコードが残っていると分かりました。そこを直して解決しました。「直したはず」を鵜呑みにせず、必ず今の状態を目で確認する。地味ですが、遠回りを防ぐ一番の近道でした。

戸惑った点2 ― サーバーに載せた瞬間の連続エラー

ローカル、つまり自分のパソコンの中だけで動かしている間は問題ありませんでした。ところが、実際のAWSに載せて動かした瞬間、続けざまにエラーが出ました。

サーバー側のプログラムには、書き方の作法(形式)がいくつかあります。今回使った新しい形式で書いたのに、ファイルの拡張子が古い形式向けのままだったため、サーバーがプログラムを読み込めずに止まりました。拡張子を新しい形式に合わせて、まず1つ解決しました。

次に、AWSを操作するための部品(ライブラリ)を、プログラムと一緒に丸ごと固めて持っていったところ、また止まりました。この部品はサーバー側にもともと備わっているので、自分で持っていく必要はありませんでした。持っていくのをやめたら動き、おまけにプログラムの大きさが1000分の1以下になりました。小さくなった分、初回の起動も軽くなります。

ここで効いたのが、エラーが出たときにサーバーの記録を見る習慣でした。記録には止まった理由がそのまま書かれていて、その一文が毎回そのまま解決の手がかりになりました。推測で直そうとせず、まず記録を読む。これに尽きました。

改善した点 ― 「初回だけ遅い」の犯人を実測で突き止めた

公開後、あるアプリの初回表示が1.5秒ほどかかることに気づきました。「サーバーに割り当てたメモリが小さいからでは」と最初は考えました。ここで推測のまま直さず、まず計測しました。

表示にかかる時間を、接続にかかった分・通信を暗号化する準備にかかった分・サーバーが考えている分、というように分けて測りました。すると遅さのほとんどが「サーバーが考えている分」に集中していました。ネットワークでも画面側でもなかったのです。

原因は、サーバーの「久しぶりの立ち上がり」でした。U-Labはアクセスが少ないので、しばらく誰も来ないとサーバーは休止します。次のアクセスで一から立ち上げ直すぶん、初回だけ時間がかかっていました。

さらに調べると、AWSを操作する部品を「必要になってから読み込む」書き方にしていたのが響いていました。この書き方は起動を軽くするための工夫ですが、サーバーでは「初回のアクセスが来て初めて読み込む」ことになり、その読み込み時間が初回の待ち時間に丸ごと乗っていました。そこで、部品の読み込みを立ち上がりの段階で一度だけ済ませる書き方に変えました。あわせてメモリも増やしました。メモリを増やすと処理する力も比例して増えるので、2回目以降の表示も速くなります。

結果、2回目以降の表示は目に見えて速くなり、初回の待ち時間も大きく縮みました。立ち上がりそのものにかかる時間はゼロにはできませんが、この規模では十分でした。「遅い=メモリ不足」と決めつけず、分けて測ったからこそ本当の原因にたどり着けた回でした。

まとめ

  • U-Labは、動くミニアプリを次々足していく実験場である
  • アプリを1個作るより、アプリを足せる土台を先に作ることを優先した
  • サーバーが要るのは「データを共有したいとき」と「秘密を隠したいとき」だけである
  • データの置き場は「誰と共有するか」で自動的に決まる
  • 手元のプログラムは見えるし書き換えられるので、守りは必ずサーバー側に置く
  • 「直したつもり」を疑い、必ず今の状態を読み直して確認する
  • サーバーに載せる形式には作法があり、エラーが出たら記録を読むのが最短の解決策である
  • 「初回だけ遅い」は推測で直さず、時間を分けて測ると本当の原因が見える

実験場なので、これからも小さなアプリを1つずつ足していきます。触って動くものが増えていく様子は、lab.ublogs.net でのぞけます。