😸

【DAY26】リアルタイム検索を導入してわかった、便利さと重さのバランス

に公開

【DAY26】リアルタイム検索を導入してわかった、便利さと重さのバランス

こんにちは、Keisukeです。
今日は、最近実装した「リアルタイム検索」機能について、その技術的背景や課題、そして改善ポイントを記録しておきます。


🔍 きっかけは「入力中でも結果が欲しい」という声

これまでの検索機能は、「検索ボタンを押したらデータ一覧が出る」という仕組みでした。
しかし、実際に自分で使っていて、「入力しながら即座に検索結果が出てきたら便利だな」と感じる場面が増え、リアルタイム検索の実装に踏み切りました。


🛠 技術的な実装方法(Firebase + JavaScript)

リアルタイム検索の基本的な流れは以下のようになります。

  1. inputイベントでユーザーの入力を取得
  2. 入力が変わるたびに、Firestoreからデータを再取得
  3. 検索結果を表示するDOMを更新

コード例は以下のような感じです:

document.getElementById("search").addEventListener("input", async (e) => {
  const keyword = e.target.value.trim();
  if (keyword.length === 0) return;

  const querySnapshot = await getDocs(collection(db, "items"));
  const filtered = querySnapshot.docs.filter(doc =>
    doc.data().title.includes(keyword)
  );
  displayResults(filtered);
});

シンプルな構造ですが、入力のたびに全データを読み込むと、非常に重くなります
特にデータ量が多くなってくると、検索ごとに何百件も取得するのは現実的ではありません。


⚠️ 課題:便利すぎると重くなる

最初は「入力するたびに即座に結果が出て最高!」と思っていたのですが、試していくうちに問題が発覚。

  • 1文字入力するたびにFirestoreへアクセス
  • データ数が100件を超えると処理がワンテンポ遅れる
  • モバイル環境では体感でラグを感じることも

つまり、「便利だけど、重い」というジレンマにぶつかりました。


🧠 解決策:デバウンスとローカルキャッシュ

そこで、次のような対策を取りました:

✅ デバウンス処理(入力から300ms待つ)

let timeout;
document.getElementById("search").addEventListener("input", (e) => {
  clearTimeout(timeout);
  timeout = setTimeout(() => {
    performSearch(e.target.value.trim());
  }, 300);
});

これにより、「連続したタイピング中の無駄なリクエスト」を防げます。

✅ 一度取得したデータをローカルに保存

起動時にFirestoreから全データを一度だけ取得し、以後はローカルでフィルタリングする形に変更。
検索精度とパフォーマンスの両立が可能になりました。


💬 結果:UX向上と負荷軽減の両立に成功

今では、1文字ずつ入力してもストレスなく検索結果が表示され、かつFirestoreへのアクセスも最小限になりました。

リアルタイム検索は、見た目以上に裏側の工夫が必要な機能です。
「使って気持ちいい体験」を技術で裏から支えることの大切さを、今回の実装を通じて改めて感じました。


ということで、DAY26は「リアルタイム検索の技術とその最適化」についての記録でした。


Discussion