ユーザーストレスを低減するローディング体験の4原則

に公開

昨今AI Agentの進化は凄まじく、ある程度AI Agent任せでもそれなりに良いUIが実装できるようになってきました。一方UX[1]を細かく作り込むには、AI Agentは明確な指示を必要とします。特にローディング体験[2]は細かい指示がなくともAI Agentがある程度よしなに実装してくれますが、筆者の理想とするような作り込みまでしてくれることはありません。これはおそらくモデルやツールの性能的な問題ではなく、プロンプトやルールを通じて行う目標設定の問題が大きいと筆者は考えています。AI Agentは実行に特化したツールであるため、明確な目標設定は人間側の責務であり、今後もしばらくは人間側の責任が大きい部分だと思われます。

この記事ではユーザーストレスを低減するローディング体験をテーマに、筆者が普段意識している原則を4つ紹介します。この記事を通して、より良いローディング体験についての学びや考えるきっかけになれば幸いです。

前提: ローディングについて

Webアプリケーションにおいてローディングとは、画面上で何かしらデータの読み込みが発生している状態のことを指します。ローディングはページ遷移時(Hard Navigation[3]やSoft Navigation[4])やデータ操作時に発生します。

ローディングUIとして代表的なものには、以下が挙げられます。

UIパターン プレビュー画像
スケルトン スケルトン
スピナー スピナー
プログレスバー プログレスバー

引用: shadcn/ui

原則1: ローディング時間の最小化

最も良いローディング体験とは、即座にコンテンツが表示されユーザーがローディングを体験しないことです。

Response Times: The 3 Important Limitsによると、ユーザー体験において留意すべき主な時間制限は3つあります。

応答時間に関する基本的なアドバイスは、30年間ほぼ同じである[Miller 1968; Card et al. 1991]。

  • 0.1秒というのは、ユーザーがシステムが瞬時に反応していると感じる限界値であり、つまり、結果を表示する以外に特別なフィードバックは必要ないということである。
  • 1.0秒は、ユーザーが遅延に気付くものの、思考の流れが途切れることなく維持される限界値と言えるでしょう。通常、0.1秒以上1.0秒未満の遅延であれば、特別なフィードバックは必要ありませんが、ユーザーはデータに直接アクセスしている感覚を失います。
  • ユーザーの注意を対話に集中させ続けるには、 10秒程度が限界です。それ以上の遅延が発生すると、ユーザーはコンピュータの処理が完了するまでの間に他の作業を行いたくなるため、コンピュータがいつ処理を完了する予定なのかを示すフィードバックを提供する必要があります。応答時間が大きく変動する可能性がある場合は、ユーザーはいつ処理が完了するのか予測できないため、遅延中のフィードバックは特に重要です。

アプリケーションが高速にコンテンツを表示できるのであれば、ユーザーにローディングをフィードバックする必要がありません。むしろ、0.1秒で消えるローディングUIは後述するような#チラつきの原因になり、ユーザーにストレスを与える可能性さえあります。

ローディング時間と体験

ローディング体験を考える上で最も重要な原則は、ローディングが高速に完了するようシステム全体を設計するということです。具体的にはCDNの活用・SQLチューニング・prefetchやキャッシュの活用などが考えられますが、パフォーマンス最適化の大原則は「推測するな、計測せよ」なので、まずは自身のアプリケーションにおけるボトルネックをLighthouseなどを用いて精査することから始めましょう。

全体を最適化した上で0.1秒の表示が達成できない部分については、ローディングUIを表示することを検討する必要があります。しかし、ローディングUIはただ表示すればいいというものではありません。残りの原則では、ローディングUIの見せ方や体験について解説します。

原則2: 多段階ローディング

Webアプリケーションにおいて0.1秒以内にコンテンツを表示するには、prefetchやキャッシュの活用がほぼ必須となってきます。言い換えると、これらが利用できないようなケースにおいて0.1秒でローディングを完了することは、非常に困難です。

このような場合においてユーザーストレスを低減するには、ローディングの分割による多段階ローディングが重要となります。ローディング体験というとローディングUIに関心が寄りがちですが、ページのローディングが多段階に設計されていることも同様に重要です。

ここでは例として、商品ページへのHard Navigationを考えてみます。商品ページが以下のように構成されていると仮定します。

コンテンツ内容 静的 / 動的 関連するデータ取得速度
静的レイアウト 静的 無し
商品情報 動的 高速(平均 0.1秒)
ユーザー情報やレコメンド 動的 低速(平均 1秒)

データ取得速度に応じてHTTP Streamingを分割(もしくはネットワーク通信を分割)すると、以下のように準備ができた部分から徐々に表示されていくような体験が実装できます。

多段階ローディング

ユーザーは、全ての準備が整ってからページが表示されることを望んでいません。段階的に準備ができた部分から表示しつつ、どこのコンテンツがローディング中なのかを知りたいと考えています。上記においてグレーアウトされた部分には、スケルトンなどを配置してローディング中であることを表すと良いでしょう。

原則3: チラつかせない

頻繁な画面更新やLayout Shiftによる、いわゆるチラつき(Flicker)はユーザーにストレスを与えます。ローディングUIとコンテンツの置き換えの実装は特に、チラつきが発生しないように工夫が必要になります。

ローディング時のチラつき対策には、スケルトンとアニメーションの組み合わせが有用だと筆者は考えています。スケルトンは置き換え後のレイアウトを表現するため、最もチラつきが少ないローディングUIです。スケルトンにアニメーションを組み合わせることでコンテンツ置き換えがよりシームレスになり、チラつきを最小限に留めることが可能です。

以下はNext.jsの<ViewTransition>Demoにおける、スケルトンとコンテンツの入れ替えアニメーションです。スケルトンが下方向にスライドした後、コンテンツが上方向にスライドしている様子が確認できます。

スケルトンのアニメーション

Next.jsにおける`<ViewTransition>`の実装例
import { Suspense, ViewTransition } from "react";

export default async function PhotoPage({ params }) {
  const { id } = await params;

  return (
    <Suspense
      fallback={
        <ViewTransition exit="slide-down">
          <PhotoContentSkeleton />
        </ViewTransition>
      }
    >
      <ViewTransition enter="slide-up" default="none">
        <PhotoContent id={id} />
      </ViewTransition>
    </Suspense>
  );
}

引用: Next.js公式ドキュメント

このように、ローディングUIはただ配置すればいいのではなく、ローディングUIとコンテンツの入れ替えを意識してUXを設計する必要があります。

原則4: 長時間ローディングのケア

チラつき同様にユーザーにストレスを与えるローディング体験として、長時間にわたってフィードバックがないことが挙げられます。原則1の通りローディング時間を最小化することは非常に重要ですが、ローディング時間がどうしても長時間に及んでしまう場合には適切なフィードバックが重要となります。

長時間かどうかの具体的な目安としては、前述の通り10秒を目安とすると良いでしょう。フィードバックが適切かどうかの判断は、コンテンツの表示が正常系[5]で何秒程度を想定するかによって変わってきます。正常系におけるローディングの想定秒数を見極めた上で、以下いずれかのパターンに沿って設計しましょう。

①正常系が〜1秒の場合: 10秒はタイムアウトとして扱う

正常系でおおよそ1秒以内に表示可能なコンテンツにおいて、10秒以上かかる場合は何かしら異常が発生している可能性が高いと思われます。データフェッチや処理自体に10秒以内のタイムアウトを設けて、タイムアウトエラーをユーザーにフィードバックしましょう。

②正常系が数秒〜10秒程度の場合: 10秒で一度フィードバック

膨大なデータ集計や複数処理が絡む場合など、正常系でも数秒〜10秒程度で表示可能なコンテンツの場合、10秒時点で「データ取得に時間がかかっています。」といった文言をローディングUI内やトーストなどでユーザーにフィードバックすることが望ましいと考えられます。

接客業において「時間がかかってしまいすみません」というコミュニケーションを行うことで、ユーザーのストレスが緩和されるのと同様です。

③正常系が数十秒〜数分の場合: 多段階フィードバック

AI生成のコンテンツなど表示に数十秒〜数分かかるようなコンテンツでは、多段階フィードバックが重要になってきます。ローディングの完了が長時間に及ぶ場合、ユーザーは定期的にどこまで完了しているか・止まっていないかを確認したいと考えるため、これらの情報が確認できるようなUXを設計することが重要です。

多段階フィードバックの例としては、Claude Codeの進行中アクションの表示("Pondering...", "Crafting..." など)やChatGPTのストリーミング表示などが挙げられます。

アンチパターン: ポップコーンUI

ここまで4つの原則について解説してきましたが、これらの原則に反する典型例として挙げられるのがポップコーンUIです。ポップコーンUIは、頻繁な画面更新とLayout Shiftを伴いながら徐々に画面が完成していく様子をポップコーンと揶揄したものです。

ポップコーンUIについては筆者の過去の記事で詳細に解説しているので、こちらをご参照ください。

https://zenn.dev/akfm/articles/popcorn-ui-anti-pattern

まとめ

ローディング体験の実装はWebにおけるおもてなしであり、開発者の誠意だと筆者は考えています。人によっては微々たる違いだと感じるかもしれませんが、こういった小さなおもてなしがアプリケーションの満足度向上やストレス軽減につながるはずです。

AI Agent時代においては開発効率が大きく叫ばれ、ツールの使い方やTipsが話題になりがちですが、AI Agentが持ちえない強い意志やこだわりこそがこれからの開発者のスキルセットとして重要であり、AI Agentを使ったアウトプット品質に大きな違いを生むことになると筆者は感じています。

ローディング体験に限らず、UXに関する議論が今後より活発になると個人的には嬉しく思います。

脚注
  1. この記事では、UIとUXを明確に呼び分けています。 ↩︎

  2. ローディングに関するUX全般を指します。 ↩︎

  3. <a>タグやリロードによるページ遷移。ブラウザ機能によるもの。 ↩︎

  4. JavaScript制御によるページ遷移。History APINavigation APIを利用する。 ↩︎

  5. システムやネットワークが正常稼働していることを想定したユースケースを指します。 ↩︎

Discussion