Fotocasa の INP の改善が主要指標の 27% の成長にどのように貢献したか

公開日: 2025 年 10 月 14 日

Interaction to Next Paint(INP)は、応答性を測定するための重要なウェブに関する主な指標です。Fotocasa では、2024 年に INP が初回入力遅延(FID)に置き換わった際に、「改善が必要」と「不良」に移行したページが多数あることが Google Search Console で明らかになりました。このケーススタディでは、これらの問題を診断して解決するために使用されたツールと戦略について説明します。最終的に、INP は大幅に改善されました。

Fotocasa チームの出発点

FID から INP への移行前は、パソコンとモバイルの両方でほぼすべてのページが「良好」のしきい値内に収まっていました。つまり、当時のウェブに関する主な指標(LCP、CLS、FID)はすべて良好なパフォーマンスを示していました。しかし、INP に移行すると、ほとんどのページが「改善が必要」に移行し、一部のページは「不良」に移行しました。これは、ほとんどのユーザー操作で INP の値が 200 ミリ秒を超えたためです。

Google Search Console に、パソコンでの Fotocasa の URL の分布が表示されています。INP が Core Web Vital になった後、多くのページが「良好」から「改善が必要」に移行しています。
図 1. Google Search Console - パソコンでの Fotocasa の URL の分布: INP が有効になると、以前は「良好」に分類されていた多くの URL が「改善が必要」のカテゴリに移動します。

この変更により、Fotocasa チームはユーザー エクスペリエンスの重要な側面を見落としていたことに気づきました。FID は最初のインタラクションの遅延のみを測定しますが、INP はすべてのインタラクションの応答性を評価し、入力処理とプレゼンテーションの遅延を考慮します。この広範な測定は、真のインタラクティビティ(Google が述べているように)をはるかに適切に表すものであり、機会損失を明らかにしました。

Google Search Console ではフィールド パフォーマンス データが提供されますが、リアルタイムの分析情報は提供されません。データは 28 日間の期間で集計されるため、どのインタラクションが問題の原因となっているかを正確に特定することは困難です。

最も遅く、ユーザーが最も頻繁に使用するインタラクションを特定し、チームの開発環境で確実に再現するために、INP をリアルタイムで追跡する方法が必要でした。同様に重要なのは、どの修正が役に立ったかだけでなく、どの調整が意図せず事態を悪化させたかなど、変更の影響を把握することでした。

そのため、一連のツールを使用して、問題の診断と解決を行いました。最も重要なものは次のとおりです。

  • Google Chrome DevTools(特に [パフォーマンス] タブ)。
  • Fotocasa チームが Datadog で web-vitals ライブラリを使用して構築したカスタム RUM(実際のユーザー モニタリング)システム。
  • React Developer Tools。

問題の診断に役立つツール

INP のパフォーマンスの問題を診断してデバッグするために、次のツールが使用されました。

Google Chrome DevTools

ウェブ アプリケーションでウェブに関する主な指標に関連する問題を検出して再現する優れた方法は、Google Chrome DevTools の [パフォーマンス] タブを使用することです。[パフォーマンス] タブでは、Core Web Vitals の指標が自動的に測定され、読み込み、インタラクティブ性、レイアウト シフトの指標に関するフィードバックが即座に提供されます。これらの指標が他の Google ツールに報告される方法とほぼ一致しています。

Google Chrome DevTools の [パフォーマンス] タブ。LCP、FID、CLS などのさまざまなパフォーマンス指標と、CPU とネットワーク アクティビティのタイムラインが表示されている。
図 2. Google Chrome DevTools の [パフォーマンス] タブ。

INP の問題を特定して解決するために、Fotocasa チームは通常、CPU をスロットリングして、ローエンド デバイスとミッドレンジ デバイスのパフォーマンスをシミュレートすることから始めました。これにより、Fotocasa チームはより制約の厳しい条件下でページがどのように動作するかを観察できるようになりました。次に、プロファイラを使用してセッションを記録し、ユーザー インタラクションに焦点を当ててトレースを慎重に分析し、パフォーマンスの問題を特定しました。

Google Chrome DevTools の [パフォーマンス] タブに、[4 倍の速度低下] や [6 倍の速度低下] などのオプションが表示された [CPU の速度低下] プルダウン メニューが表示されている様子。
図 3. Google Chrome DevTools の [パフォーマンス] タブに、CPU スローダウンのプルダウンが表示されている様子。

ボトルネックを特定する際は、INP のサブパートと、ブラウザが各サブパート内で実行するタスクを調べると特に効果的です。たとえば、次の画像では、ドキュメントの本文のスタイルの変更によって 2 回のスタイルの再計算が発生したため、INP がかなり高くなっています。

Google Chrome DevTools の [パフォーマンス] タブに、プロファイラで長いタスクが表示されています。詳細には、2 回のスタイルの再計算が原因で INP が高くなっていることが示されています。
図 4. Google Chrome DevTools の [パフォーマンス] タブに、プロファイラが入力された状態で表示されている様子。

Fotocasa は、INP やその他のコア ウェブ バイタル指標を追跡するシステムをセットアップし、パフォーマンスの問題を迅速に特定して対処できるようにしました。指標が特定のしきい値(Google が定義した範囲に基づく)を超えると、アトリビューションが記録され、問題を分析して解決できるようになります。

このシステムでは、web-vitals ライブラリを使用して、Chrome で測定され、他の Google ツール(Chrome ユーザー エクスペリエンス レポート、Page Speed Insights、Search Console の速度レポートなど)に報告される方法と正確に一致する方法で、実際のユーザーからこれらの指標を取得しました。

包括的なビューと一元的な追跡を実現するため、Fotocasa は Datadog を使用してデータを収集、可視化し、チームが情報に基づいたデータドリブンな意思決定を行えるようにしました。カスタム指標を使用することで、費用対効果を維持しつつ、Fotocasa ウェブサイトのほぼすべてのユーザーをより正確にトラッキングできるようになりました。

Fotocasa の Datadog ダッシュボードに、INP、LCP、CLS などのさまざまなパフォーマンス指標の推移が表示されています。
図 5. Fotocasa Datadog パフォーマンス RUM ダッシュボード。
入力遅延、処理時間、プレゼンテーション遅延の指標のグラフを表示する Datadog ダッシュボード。
図 6. 入力遅延、処理時間、プレゼンテーション遅延の指標。

このシステムにより、Fotocase チームは、変更が指標に影響するかどうか、予期しない変更が発生して指標が損なわれる可能性があるかどうかを迅速にモニタリングできます。INP 指標は、入力遅延、処理時間、表示遅延などの部分に分解して、インタラクションのどの部分がインタラクション時間の長さに主に影響しているかを正確に特定できます。

INP 値の急激な上昇を示す Datadog のグラフ。異常を示しています。
図 7. ダッシュボードで検出された INP 異常。
Datadog のモニター アラートに、検出された INP の異常が表示されている。
図 8. モニター アラームで検出された INP 異常。

Fotocasa は、図 7 と図 8 に示すような異常を検出すると、直ちに対応し、OpenSearch を使用して、変更が発生している可能性のある場所を特定しました。web-vitals ライブラリから提供されたデータは、ターゲット(指標値の上昇の原因となっている可能性のある DOM 要素)の特定に役立ち、チームが問題の修正に集中するのに役立ちました。

ウェブバイタル ライブラリのデータを表示する OpenSearch ダッシュボード。INP 指標に影響している DOM 要素を特定するために使用されます。
図 9. OpenSearch ダッシュボードを開いて、どのターゲットが INP 指標に影響しているかをデバッグします。

さらに、ページタイプ、デバイス、読み込み状態などのさまざまなフィルタを定義してシナリオを絞り込み、INP がどのように影響を受けているかをより正確に把握できます。

React Developer Tools

React Developer Tools を使用して Fotocasa のデバッグ機能を強化しました。このツールには、再レンダリングされたコンポーネントを視覚的にハイライト表示できる強力な機能があります。

この機能は、[Profiler] タブに移動して有効にできます。そこから、上部のバーの右側にある歯車アイコンをクリックし、[全般] タブに移動して、[コンポーネントのレンダリング時に更新をハイライト表示する] チェックボックスをオンにします。この機能を有効にすると、コンポーネントが再レンダリングされるときにハイライト表示され、動的な視覚表現が提供されます。

React Developer Tools の設定パネルで、[コンポーネントのレンダリング時に更新をハイライト表示する] チェックボックスがオンになっている。
図 10. プロファイラ構成の React Developer Tools。

再レンダリングの原因を特定する

再レンダリングされたコンポーネントが特定されたら、次の質問は「なぜ再レンダリングされたのか」です。React DevTools は、フレーム グラフ ビューの便利なツールチップでこの質問に答えます。

この情報にアクセスするには、プロファイラ セッションを記録します。プロファイラの出力を分析すると、次のような有用な情報が得られます。

  • 右上には、React のコミット数が表示されます。
  • フレームグラフはコンポーネント ツリーを視覚的に表したもので、グレーは再レンダリングされなかったコンポーネントを示しています。各バーは、React コンポーネント ツリーが変更されたときと、対応する変更が DOM にコミットされたときを表します。
  • フレーム グラフの各コンポーネントにカーソルを合わせると、その再レンダリングの理由が [Why did this render?](なぜこのレンダリングが行われたのか)という小見出しの下に表示されます。

コンポーネントの再レンダリングの理由としては、次のようなものが考えられます。

  • コンポーネントが初めてレンダリングされたかどうか
  • コンテキストが変更されました
  • フックが変更されました
  • Props が変更された
  • [都道府県] が変更されました
  • 親コンポーネントがレンダリングされた
React Developer Tools のプロファイラにフレームグラフが表示され、コンポーネントのツールチップが開いており、「Hooks changed」が原因で再レンダリングされたことが説明されている。
図 11. React Developer Tools プロファイラのレンダリング パネル。

レンダリング時間を調べる

フレームグラフの色は、意味のある情報を伝えます。さまざまな青の色合いは、他のコンポーネントと比較して、コンポーネントのレンダリング時間が比較的短いことを示します。逆に、オレンジや赤などの色は、コンポーネントのレンダリングに時間がかかったことを示します。

React Developer Tools のプロファイラに、レンダリング時間を色で示すフレームグラフが表示されている。青の濃淡は短い時間を、オレンジ色と赤色の濃淡は長い時間を表している。
図 12. React Developer Tools のプロファイラに表示されるレンダリング時間。

Fotocasa チームが問題を解決した方法

不要な再レンダリングを削除する

再レンダリングは、React が新しいデータで UI を更新する必要があるたびに発生します。通常、これはユーザー操作、API レスポンス、またはユーザー インターフェースの更新を必要とするその他の重要なイベントから発生します。再レンダリングごとに JavaScript が実行されるため、特に大きなコンポーネント ツリーで再レンダリングが一度に多数実行されると、メインスレッドがブロックされ、パフォーマンスの問題が発生する可能性があります。

再レンダリングには次の 2 種類があります。

  • 必要な再レンダリング: コンポーネントが新しいデータを所有または使用しているため、更新が必要な場合。
  • 不要な再レンダリング: 効率の悪い状態管理や不適切なプロパティ処理が原因で、コンポーネントが意味のある変更なしに更新される場合。

不要な再レンダリングが数回発生しても、React は十分に高速であるため、通常はユーザーが気づくことはありません。ただし、頻繁に発生したり、コンポーネント ツリーの深いところで発生したりすると、ユーザー エクスペリエンスが損なわれ、ページの INP に悪影響が及ぶ可能性があります。

Fotocasa チームも同様でした。ウェブサイトで不要な再レンダリングが多数発生していることに気づきました。これらの問題は、主に次の 2 つのシナリオで発生しました。

  • ページの読み込み中: メインスレッドでの長時間タスクの数が増加し、初回操作が遅延したため、ページの INP に悪影響を及ぼしました。
  • ユーザー インタラクション中: ほとんどのインタラクションの処理時間を増やし、INP も悪化させました。

Fotocasa のウェブサイトでは、不要な再レンダリングが多数最適化されました。特に大きな最適化が実現したのは検索ページです。ページの読み込み時に不要な再レンダリングが 3 回発生していました。これらを削除したところ、次の結果が得られました。

  • 長いタスクの数が少ない(次の図を参照)
  • Total Blocking Time の短縮(図 14 と図 15 を比較)
Chrome DevTools のメインスレッドのスナップショット 2 つ。上のスナップショットは最適化前の長いタスクの数を示し、下のスナップショットは不要な再レンダリングを削除した後の長いタスクの数を示しています。
図 13. 不要な再レンダリングがある場合とない場合のメインスレッドのスナップショット。
Lighthouse のモバイル パフォーマンス レポート。合計ブロック時間が 1,080 ミリ秒と表示されており、不要な再レンダリングが原因でパフォーマンスの問題が発生していることを示しています。
図 14. 不要な再レンダリングを示す Lighthouse モバイル パフォーマンス レポート。
不要な再レンダリングを削除したことで、合計ブロック時間が大幅に短縮されたことを示す Lighthouse モバイル パフォーマンス レポート。
図 15. 不要な再レンダリングのない Lighthouse モバイル パフォーマンス レポート。

状態のコロケーション

React の状態を適切に配置しないと、アプリケーションの速度が低下し、UI の応答が遅くなることがあります。コンポーネントの状態が変化すると、エスケープ ハッチ(メモなど)が使用されない限り、その子コンポーネントはデフォルトで再レンダリングされます。

前のセクションで説明したように、再レンダリング自体は悪いことではありませんが、特定の状態更新によってページ全体が再レンダリングされると、レンダリング後に DOM の更新が行われるため、インタラクションが遅くなる可能性があります。

たとえば、検索ページには、ボタンをクリックするとすべてのフィルタが表示されるダイアログがあります。

Fotocasa の検索ページのフィルタバー。すべてのフィルタを含むダイアログを開くボタンが表示されています。
図 16. Fotocasa のフィルタバー。

この場合、ダイアログの開閉状態を制御する状態は検索ページに配置されました。この状態が変更されると、ページ全体が再レンダリングされ、INP が悪化していました。特に、DevTools で CPU スロットリングを使用した場合に、低速のデバイスでこの現象が顕著でした。

CPU スロットリング INP
4 倍の減速 440 ミリ秒(改善が必要)
6 倍減速 832 ミリ秒(悪い)

変更をトリガーするコンポーネントにできるだけ近い状態で状態を変更すると、この問題は解決します。この場合、状態をフィルタのボタン コンポーネントに配置して、状態が変化したときにボタンのみが再レンダリングされるようにします。

CPU スロットリング INP
4 倍の減速 64 ミリ秒(良好)
6 倍減速 232 ミリ秒(改善が必要)

不要な状態を削除する

状態に冗長な情報や重複する情報を含めるべきではありません。そうすると、不要な再レンダリングが発生し、問題が生じる可能性があります。

たとえば、Fotocasa のフィルタバーには、特定の検索に適用されたフィルタの数を表すテキストが表示されます。

Fotocasa のフィルタバー。適用されたフィルタの数を示す数字が表示された [フィルタ] というラベルのボタンが表示されています。
図 17. Fotocasa のフィルタボタンとカウンタ。

適用されたフィルタの数は、アプリの状態から計算されます。しかし、これによりコンポーネント全体が不必要に再レンダリングされるだけでなく、このコンポーネントはサーバーサイドでレンダリングされるため、レイアウト シフトが発生することもありました。

const [filtersCount, setFiltersCount] = useState(DEFAULT_COUNTER)

useEffect(() => {
  const counter = filters
    ? Object.keys(filters)
        ?.reduce(reducerCounter, [])
        ?.filter((param) => searchParams?.[param]).length
    : DEFAULT_COUNTER

  setFiltersCount(counter)
}, [searchParams]);

この問題を解決するため、状態を使用する代わりに、変数を使用してフィルタ オブジェクトから値を取得しました。

const counter = filters
    ? Object.keys(filters)
        ?.reduce(reducerCounter, [])
        ?.filter((param) => searchParams?.[param]).length
    : DEFAULT_COUNTER;

コストのかかるレンダリングを減らす

React アプリケーションでインタラクションが発生すると、通常は状態の変更がトリガーされます。前述のとおり、コンポーネントの状態が変化すると、そのコンポーネントとそのすべての子が再レンダリングされます。

これらのコンポーネントのレンダリング関数のいずれかが遅いと、長いタスクが生成され、DOM の更新に時間がかかるため、ページの INP に悪影響を及ぼします。

Fotocasa チームは、コンポーネントのレンダリング関数内の時間のかかる計算をできるだけ最小限に抑えようとしました。Chrome DevTools と React Developer Tools は、レンダリングの遅いオペレーションを検出するのに非常に役立ちました。

コードの実行を遅延させる

コンポーネントのレンダリング関数の最適化に加えて、他の関数も最適化され、長いタスクが可能な限り最小限に抑えられました。ただし、一部のタスクはサードパーティのコードに依存しているため、最適化できませんでした。

たとえば、分析です。この場合、ユーザー操作が発生したときに分析コードの実行を遅らせ、DOM の更新を優先することにしました。これを実現するため、Fotocasa チームは idlefy というライブラリを使用しました。これにより、ブラウザがすぐに閉じられた場合でも、分析コードが実行されることが保証されました。

パフォーマンス文化

パフォーマンスの改善は 1 回限りの取り組みではなく、本番環境にリリースされるすべての機能で考慮する必要があります。チームの全員が足並みを揃える必要があります。そうしないと、Core Web Vitals の回帰はほぼ避けられません。

この問題を解決するため、Fotocasa チームはチーム内で積極的に知識を共有し、Fotocasa の Datadog RUM データに基づいてパフォーマンスの問題を特定するための明確なフレームワーク(問題の再現方法など)を確立しました。RUM システムで Core Web Vitals(特に INP)のアラートを設定し、Slack で Fotocasa チームに直接通知するように構成しました。このアプローチにより、パフォーマンスを常に意識し、問題が回帰になる前に検出することができました。

結果

Fotocasa で INP を改善するには、技術的な最適化と文化的な変化を組み合わせる必要がありました。不要な再レンダリングを排除し、状態の配置を最適化し、コストのかかるレンダリングを削減し、重要でないコードを遅延させることで、Fotocasa チームはすべてのパソコン用ページを「改善が必要」から「良好」に移行し、モバイル用ページを大幅に改善しました。ほぼすべての「不良」と「改善が必要」なページを「良好」にアップグレードしました。

INP の改善後、パソコンの Fotocasa の Core Web Vitals が Google Search Console に表示されている。
図 18. INP の改善後、Google Search Console にパソコン版の Fotocasa の Core Web Vitals が表示されている。

これらの変更により、Fotocasa のユーザー エクスペリエンス全体が向上し、他の取り組みと合わせて、問い合わせと電話のリード広告が 27% 増加しました。これにより、同社の主要なビジネス指標が直接的に強化されました。

Datadog によるリアルタイム モニタリングにより、Fotocasa チームは INP の改善を検証し、異常を迅速に検出し、回帰を防ぐことができました。これらの成果に加えて、Fotocasa はウェブ パフォーマンスを開発文化に組み込むことにも成功し、INP と Core Web Vitals がすべてのリリースで優先事項として扱われるようにしました。