結論:この記事で伝えたいこと
人を預かる施設の職員が現場で写真を撮影し、施設内やご家族と共有するためのスマートフォンアプリを開発しました。この案件で最大の論点は、機能の豊富さではなく 「撮影した写真を、撮影者の端末に残さないこと」 でした。
やったことは、突き詰めれば次の2点です。
- 写真の保存先を、端末の通常の写真フォルダではなく アプリだけが触れる専用の保管場所 にする
- サーバーへのアップロードが完了したら、端末側の写真を 自動的に消す
そして実務上もっと重要だったのが、「アップロードは失敗する前提で設計する」 ことでした。自動で消す仕組みは、消すタイミングを一つ間違えると「写真が消えたのに、どこにも残っていない」という最悪の事故に直結します。以下、その中身と、うまくいかなかった点を書きます。
業界・業種
福祉・教育系の、人を日常的にお預かりする施設向けのサービス開発です。
発注者は何に困っていたのか?
施設の職員が日々の様子を撮影し、その写真を施設内で共有したりご家族へ届けたりする ―― 発想としてはごく自然な業務です。しかし、これを普通のスマートフォンで実現しようとすると、避けて通れない問題が出てきます。
撮った写真が、撮影に使った端末の中に残り続ける という問題です。
スマートフォンの標準のカメラで撮影すると、写真はその端末の写真フォルダ(カメラロール)に保存されます。ここに入った写真は、他のアプリからも参照できますし、SNSやメッセージアプリで送ることもできます。端末を紛失すれば、写真もまるごと外に出ていきます。
お預かりしている方の写真は、ご本人とご家族にとって最も繊細な個人情報のひとつです。「職員が悪意を持っていなければ大丈夫」という運用ルールだけでは、施設としてリスクを引き受けきれません。仕組みとして、写真が端末に残らないようにする必要がありました。
これが、この案件の出発点にあった要件です。
どう解決したのか?
撮影から共有までの流れを、アプリの内側で完結させました。
- 職員は、アプリ内のカメラ機能で撮影する(標準のカメラアプリは使わない)
- 撮影した写真は、アプリ専用の保存領域に置かれる。端末の写真フォルダには入らない
- アプリがサーバーへ自動でアップロードする
- アップロードの完了を確認できたら、端末側の写真を自動的に削除する
- 以降、写真の閲覧はすべてサーバー上のデータに対して行う
「アプリ専用の保存領域」というのは、スマートフォンのOSが各アプリに割り当てている、そのアプリしか読み書きできない領域のことです。ここに置かれたファイルは、他のアプリからは見えません。写真フォルダに保存するのと比べて、外に持ち出される経路が大幅に減ります。
見られる範囲についても、次のように整理しました。
- 撮影者本人は、自分がアップロードした写真を見られる
- 施設への共有を許可した写真は、その施設に所属する他のユーザーも見られる
つまり、共有は「許可した写真だけ」が対象で、撮っただけの写真が自動的に他の職員に見えることはありません。
どこまで担当したのか?
要件定義からリリースまでを担当しました。運用開始日程が未定だったため、保守・運用フェーズには入っていません。
体制はアプリ側・サーバー側あわせて数名の少人数チームです。私はプロジェクトマネージャーとして顧客との折衝や仕様調整をほぼ一手に引き受けつつ、自分でもアプリとサーバー両方のコードを書く、いわゆるプレイングマネージャーの立ち位置でした。
何を使って作ったのか?
- スマートフォンアプリ:Flutter(1つのソースコードからiOS・Android両方のアプリを作れる開発ツール)
- サーバー側:PHP/Laravel(Webシステムを作るための代表的な言語と、その土台となる枠組み)
- クラウド基盤:AWS の EC2(サーバー)、RDS(データベース)、S3(写真などファイルの保管庫)
特別に新しい技術は使っていません。写真という壊れては困るデータを扱う以上、実績のある構成を選ぶ方が理にかなっていると判断しました。
一番工夫したのはどこか? ― 「消す」より「失敗を前提にする」こと
先に書いたとおり、この案件の肝は「アップロードが終わったら端末から消す」という部分です。ただ、実装してみるとすぐに分かるのですが、難しいのは消すことではなく、消してよい状態かどうかを見極めることです。
現場は、通信環境が安定しているとは限りません。屋外にいれば電波が弱いこともあれば、外出先の行事に出ていることもあります。目の前の対応をしながらの撮影ですから、職員がアップロードの完了を毎回画面で確認する、という運用も現実的ではありません。
そこで、次のような仕組みにしました。
- アップロードに失敗した写真には 「失敗」の印を付けて端末内に残す(この段階では絶対に消さない)
- 失敗した写真は、手動で再アップロードできる
- 加えて、次にアプリを起動したときに自動で再送を試みる
職員が何もしなくても、電波の届く場所でアプリを開けば、前回送れなかった写真が勝手に送られていく、という状態を目指した形です。
ここでお伝えしたいのは、「自動で消す」という要件が出てきたときに考えるべきなのは、うまくいったときの動きではなく、失敗したときに何が残るかだということです。成功時の流れは誰でも思い付きますが、事故が起きるのは必ず失敗経路の側です。
うまくいかなかったことは?
この案件で私が最も反省しているのは、画面デザインで合意できたことを、動きの合意だと思い込んでしまったことです。
写真ビューア(撮った写真を一覧で見て、選んで拡大表示する画面)について、見た目のデザインはクライアントと丁寧にすり合わせ、認識も揃っていました。ところが実物が動き始めると、細かい挙動でクライアントの期待とのズレが次々に出てきました。
代表的なものが、写真を拡大表示している状態で 左右にスワイプして前後の写真へ移動できない、という点です。私たちは「一覧に戻ってから次の写真を選ぶ」動きとして作っていました。しかしクライアントの頭の中には、普段使っているスマートフォンの写真アプリの体験があります。拡大したままスワイプで次々に送れるのが当たり前 ―― その前提は、デザイン画には一切現れません。
静止画のデザインは、静止画のことしか合意していない。 当たり前のようでいて、実際に痛い目を見るまで身に染みなかった教訓です。
もう一つ苦労したのが、写真一覧のスクロールです。一覧を下にスクロールしていくと続きの写真を追加で読み込む、という一般的な作りにしたのですが、すでに読み込み済みの写真を一部重複して取得してしまう挙動の解消に、かなり時間を取られました。写真が次々と増えていくサービスでは、こうした「読み込みの継ぎ目」の処理が地味に難物です。
所感 ―― これから開発を発注する方へ
1つ目。「安全に扱いたい」は、機能ではなく設計として依頼してください。
「写真が漏れないようにしたい」という要望を、パスワードをかける、閲覧権限を分ける、といった機能の話として片付けてしまうと、肝心の「そもそも端末に残っている」という穴が塞がりません。何を防ぎたいのかを最初に言葉にしておくと、開発側は仕組みそのものを設計できます。
2つ目。デザインが決まっても、動きは決まっていません。
画面が並んだデザインを見て「これでOK」と言いたくなる気持ちは、発注側・開発側の双方にあります。ですが、スワイプ、スクロール、読み込み中の表示、失敗したときの見え方 ―― これらは静止画には映りません。可能であれば、画面を触れる試作品の段階でひと通り操作してみることを強くおすすめします。手戻りのコストが桁違いに変わります。
3つ目。うまくいかないときの動きを、先に決めておくと強い。
通信が切れた、アップロードに失敗した、途中でアプリを閉じた。現場で必ず起きるこうした場面の扱いを最初に決めておくと、そのシステムは目に見えて壊れにくくなります。地味で、見積もりの中では目立たない部分ですが、実際に運用が始まってから効いてくるのはここです。
ーーーーーーーーーーーーーーーー
筆者
佐々木泰貴(テックビーンズ株式会社)
通信インフラからWeb・モバイルアプリまで技術領域の広い「実装もできるPM」。品質最重視の通信インフラ開発で本番バグ流出ゼロを3年間継続した経験を土台に、要件定義から運用まで一気通貫で担当。顧客の要望を実現可能な仕様に落とし込み、開発チームが迷わず動ける状態を作ることが強みです
この記事の内容について、直接聞いてみませんか?
「うちの場合はどうなる?」「こんなことはできる?」——そのレベルのご質問で大丈夫です。プロフィールページから佐々木泰貴に直接メッセージを送れます。
[ 佐々木泰貴にメッセージを送る ]
