ロコガイド テックブログ

「地域のくらしを、かしこく、たのしく」する、株式会社ロコガイドの社員がいろいろな記事を書いています。

「地域のくらしを、かしこく、たのしく」する、株式会社ロコガイドの社員がいろいろな記事を書いています。

エンジニアドリブンでユーザー体験を約250%改善した話

f:id:nnnnn15z:20190308125320p:plain

こんにちは、技術部の@k0uhashi👻です。最近の休日の過ごし方はVRChatを朝から次の日の朝までやることです。一瞬で月曜日が来るのでオススメです。業務では主にトクバイiOSアプリの開発をしています。

トクバイAndroid/iOSアプリはおトクな体験をより身近にし、もっと買い物をかしこく、たのしくできるようにアップデートを日々重ねています。
みなさんは、サービス開発を進めるにあたってどんな施策をやっていますか?それってどうやって考えてますか?さらにはどうやって進めていますか?アプリの体験を良くするための施策を考える中で、アプリ内で提供するコンテンツを増やしたり、UIを変えてA/BテストしてよりよいUIに変えるーーー。といった目で見てわかりやすい変化をつけることに目を向けがちですが、それ以外にも体験を良くする方法ってたくさんあるはずです。例えば、次のようなものとか。

  • 読み込み待ち時間を短縮
    • ネットワークパフォーマンス改善
  • ぬるぬる動くUIにする
    • UIパフォーマンス改善
  • 初回起動時間の短縮
    • 初回起動処理のパフォーマンス改善
  • etc...

しかし、これらの改善は完全に技術的な要件で、エンジニア以外に改善を提案するのって難しいと思います。
そこで、トクバイのアプリチームではエンジニアから改善を提案し2ヶ月程掛けてアプリを改善していきました。今回はその改善する中でどのように進めたか?どんな結果が出たか?をお話していこうと思います。

エンジニア主導で改善を提案

エンジニアから改善を提案する!といっても何からやればいいかわからない上に、本当にユーザ体験がよくなるかどうかもわかりません。(これ以外にも当てはまりますが。)

  • 不安ポイント
    • 本当にユーザー体験が良くなるのか?
    • 何からやれば良い?

このポイントを元にモバイルエンジニアで集まりアイデア出しを行い、次のような方針で進めることにしました。

  • 本当にユーザ体験がよくなるのか?👇
    • 必要最小限で、費用対効果が高そうなところを期間を限定してやっていく
      • 必要最小限
        • モバイルエンジニアだけでできる
      • 費用対効果が高そうなところ
        • よく見られている画面・機能
        • 改善の余地が大きそうな画面
  • 何からやれば良い?👇
    • パフォーマンス計測でボトルネックを見つけて費用対効果が高そうなところをやる

方針が決まったところで、ここからはじゃあどんな改善をやっていくか?をアイデア出ししていきます。
いくつかアイデアは出ましたが、現時点ではモバイルエンジニアだけで完結できるUIパフォーマンス改善が一番よさそうという結論に至り、進めることになりました。

どのくらいの工数をかけるか?

進めるとはいったものの、いつやるか?どのくらい工数をかけるか?どこまでやるか?
一般的な自社サービス系の開発チームではロードマップが敷かれていて、それに沿って色々な機能を追加したり改修を進めていて、1スプリントまるまるパフォーマンス改善に使えるのってあまりないかと思います。そのことも踏まえて次のように決めました。

  • 工数
    • 前提: トクバイのモバイルアプリ開発チームではスクラム開発を採用していて、1スプリント2週間のサイクルで開発している
    • 2週間のうち約2日を工数として充てる
  • 期間
    • 2ヶ月

ここらへんは決めの問題もあるかと思います。他の施策をやりつつ改善がうまい具合に進められるラインがこれくらいかなーというエンジニアの感覚を大事にしました。

どんなスケジュールで改善していく?

段階を分けたほうが進めやすいため、今回は次のとおりに進めました。

  • Step1
    • 指標の決定
    • 対象画面の決定
    • パフォーマンス計測方法の確立
  • Step2
    • 計測とボトルネックの発見
      • issueを立てる
    • 他社事例から改善案を出し合う
  • Step3
    • インパクトのありそうなものからissueを進め、検証する
    • ある程度効果が見込めそうならmasterブランチへmergeする
  • Step4
    • 最高な体験をユーザへ届ける!

指標の決定

ログを仕込んで計測するのも良いですが、今回は必要最小限でスタートしたいため既存のツールを使って指標を決めます。

iOSアプリの改善の場合

トクバイiOSアプリの改善を例に取り上げると、今回はiOSアプリのパフォーマンス数値を簡単に一覧表示できるFirebase Performance を使用しました。

f:id:nnnnn15z:20190308130928p:plain
Firebase Performanceの画面

  • Firebase Performance
    • レンダリング
      • 遅いレンダリング
      • フリーズしたレンダリング

上記の2つの数値を指標にし、ここを下げていくことを目標に設定しました。

対象画面の決定

  • アプリのメイン機能となる画面(もしくはその導線)
  • 閲覧数の多い画面

Firebase Performanceを使う場合

  • 遅いレンダリングフリーズしたレンダリングの割合が大きい画面

トクバイアプリではトップページとお店の情報を見ることができる画面が項目に適していたため、この2つを対象に改善していくことにしました。

パフォーマンス計測方法の確立

パフォーマンス計測方法も必要最小限で進められるように既存のツールを使いましょう!

iOSアプリのパフォーマンス計測

iOSアプリのパフォーマンス計測には、XcodeのツールセットにあるInstrumentsを使用し、次のプロファイラーを使って計測していきます。

f:id:nnnnn15z:20190308125158p:plain
XcodeからInstrumentsを起動する

  • Instruments
    • Time Profiler
      • システムのCPU上で実行されているプロセスの時間ベースのサンプリングができる
      • CPU負荷の時系列グラフ
        • 各スレッドでどのくらい負荷がかかっているか?(時間)
    • Core Animation
      • アプリケーションのFPSを表示してくれる

Tips Instrumentsには他にも循環参照を発見できるLeaksやバッテリー消耗量を確認できるEnergy Logといった強力なツールも用意されています

計測とボトルネックの発見

ボトルネックを探すのは簡単です。InstrumentTime Profilerを開き、Recordボタンからアプリのパフォーマンスを計測開始できます。開始したら計測したい画面をぐりぐり動かし、ある程度のところで一時停止します。

f:id:nnnnn15z:20190308125320p:plain

この状態だと、System Libraryのログが入って少し見辛くなってしまうので、下部のCall Treeを開きTop function, Hide System Librariesのチェックを✅にすると見やすくなります。

f:id:nnnnn15z:20190308125404p:plain
Time Profilerをもっと便利に

あとは下部のリストの最上部を選択し、キーボード入力で➔↓➔↓➔↓➔↓➔↓➔↓➔… 一番最下層までたどり着きましたか?そいつがネックです!👮‍♀️🚨

f:id:nnnnn15z:20190308125738p:plain
🚨ボトルネック🚨

issueをたてて、つぶす。

ネック部分を見つけたら、順次issueをたてていきます。

f:id:nnnnn15z:20190308125920p:plain
どんどんissueを立てていく

作成したissueはGitHub Projectsを使ってタスク管理し、あとはやりたい人がアサイン付けて地道に潰していきます。

f:id:nnnnn15z:20190308130008p:plain
GitHub Project を使ってタスク管理

実際に修正した問題

f:id:nnnnn15z:20190308143944g:plain
スクロール in スクロール

トクバイiOSアプリの一部の画面では、👆のようなスクロールinスクロール(名称不明)なUIを使っています。 このUIを作る時、みなさんはどんな手段を使って実装しますか?

  1. UICollectionView + UICollectionViewCell in UIScrollView + 複数のUIView
  2. UICollectionView + UICollectionViewCell in UIScrollView + UIStackView
  3. UICollectionView + UICollectionViewCell in UICollectionView
  4. ...等

UIKitには様々なパーツが用意されていて、上記のように様々な手段で作れます。 トクバイiOSアプリでは、このUIを1.の手段で実装していました。UIScrollViewに対して横方向にaddSubView,addSubView,addSubView... という感じですね。

iOSでどんな形で表現されるかというと、次のようになります。

f:id:nnnnn15z:20190308130540p:plain
addSubViewで作る

  • 階層イメージ
  • UICollectionView
    • UICollectionViewCell
      • UIScrollView
        • UIView
        • UIView
        • ..

はい、ここがネックでした。お察しの方も多いと思いますがあえて書かせてください。
仮にここが10枚、15枚、極端ですが100枚あった場合、100回UIViewを生成しaddSubViewします。

f:id:nnnnn15z:20190308130605p:plain
CollectionViewを使う

むっちゃ重いです。生成したView、使い回せたらいいですね。ということでView(セル)を使い回すことのできるUICollectionViewを使うように修正します。

  • 階層イメージ
  • UICollectionView
    • UICollectionViewCell
      • UICollectionView
        • UICollectionCell
        • UICollectionCell
        • ..

UICollectionViewを使うことによって、どんなにデータがあったとしてもUIの生成時間は表示されている分だけで済むので大幅な速度改善が見込めます!(再利用するときの処理時間はもちろんかかりますが、生成時間に比べるとかなり短くなります。)

実際に、データが7個の場合で速度を測ってみると、約1.7倍ほどパフォーマンスが上がりました 🎉

2ヶ月間改善を進めてみて

地道に改善を重ねた結果・・・

Firebase Performance レンダリング フリーズしたフレームの値 (その画面の読み込みに0.7秒以上かかった人がが0.1%以上いる人の割合) ≒ 画面が一時的にフリーズする人

View名 修正前 修正後
NavigationController 9.12% 7.76%
MainPageViewController(最下層のViewController) 10.70% 8.91%
TabBarController 9.71% 8.18%
TopViewController 6.43% 5.45%
ShopTopViewController(お店の画面) 2.32% 1.72%

※上記画面一覧はアプリのメイン機能(&導線)画面閲覧数の多い画面フリーズしたレンダリングの数値が大きい画面に該当する画面

画面が一時的にフリーズする人が全体的に約2%減った!🎉
全体で見れば影響範囲は少ない&元々動作が軽いアプリなので大きく減らすことはできませんでしたが、この約2%のユーザーには確実に良い体験を届けることができました。
数値的には小さな改善ですが、3,4世代前の機種であるiPhoneSEiPhone6から見てみると圧倒的な差があるのが見てわかります。

修正前 平均20FPS 修正後 平均50FPS
f:id:nnnnn15z:20190308144132g:plain
修正前
f:id:nnnnn15z:20190308144223g:plain
修正後

機種にもよりますが、古い端末ではFPSの平均がなんと約250%も向上してました!やったーー🎉

まとめ

  • 技術的な改善の提案はエンジニア以外にするのは難しい
  • 技術的な改善はまずは 必要最小限で、費用対効果が高そうなところを期間を限定してやっていく
  • 指標とパフォーマンス計測は既存のツールを使う
  • ネックを見つけたらどんどんissueを立て、タスク管理していく
  • 最高な体験をユーザへ届ける!

以下、チラシの裏に書いたメモ

冒頭でも述べましたが、アプリの体験をよくする方法っていっぱいあると思います。その中で、施策を考えるのはディレクターの役目、UIはデザイナーの役目、実装はエンジニアの役目、という風に考えるのではなく、一緒に一つのものを作るチームですからそんな垣根を越えて良い具合に連携して、役割ごとの強みを上手く交差させて、良いプロダクトを作れると最高ですね