Reddit の iOS アプリのエクスペリエンスが Web バージョンよりも優れていることがわかったので、データの読み込みが速い理由を調べてみようと思いました。以下は Reddit の iOS アプリの分解です。
以下にハイライトをいくつか紹介します。
- トークンベースの認証を使用します。
- 設定や実験から投稿情報まで、ほぼすべてに GraphQL API を使用します。
- w3-reporting という API を使用して、ユーザーが体験する API システムのパフォーマンスを監視します。
- ほとんどの GraphQL API 呼び出しでは、変数なしで操作名のみが渡されます。これは、フロントエンドから変数の構成を抽象化するためにミドルウェアを使用していると想定しています。バックエンド サービスは、操作名に基づいて情報を入力します。
- Reddit はライブコメント機能に Web Socket を使用します。
API 呼び出しの詳細な分解は、こちらにあります。Reddit の iOS アプリを傍受するためにRequestly のデスクトップ アプリを使用しました。セットアップ手順は、こちらで提供されています。
使用される技術
Redditアプリは
- Reddit の iOS アプリは、GraphQL API を使用してすべてのコンテンツを読み込みます。
- トークンベースの認証はユーザーの検証に使用されます。
- ユーザー側で API パフォーマンスを報告することによるパフォーマンス監視。
- ライブコメントは WebSocket を使用してサポートされます。
- 新しいバージョンを展開せずにアプリの動作をリモートで制御するための動的構成。
- 実験のステータスを変更するために新しいデプロイメントを必要とせず、実験をリモートで制御する動的実験。
プリロードによるUXの向上
私が抱いていた主な疑問は、アプリがなぜこんなに高速に動作するのかということでした。これは、 FeedPostDetailsByIds API の応答を確認することで解決しました。この API は、表示される投稿の ID とともにホーム画面で呼び出され、投稿をクリックした後に表示される詳細情報が付属しています。トップ投稿のこの事前読み込みにより、ローダーなしで投稿の詳細画面を即座に表示できるようになりました。
- プリロード中の投稿はフィードに表示されます。
- API の応答時間も非常に高速です。
GraphQL API セキュリティ
GraphQL クエリは、必要な応答のデータと構造で構成されます。操作名は通常オプションです。ほとんどの Reddit API では、クエリに操作名のみが含まれており、変数は、ホット投稿や最新投稿のオプションを含むフィードなどの画面上の変数/フィルターがある場合にのみ使用できます。
これにより、フロントエンド開発者が独自に変更を加えるための制御は少なくなりますが、ユーザー向けの API の後に不要なデータを取得するために API を誤用することに対する制御は強化されます。
遠隔制御実験
ネイティブ iOS アプリで実験を実行するのは難しく、実験を有効または無効にするには再デプロイが必要ですが、Reddit は実験をリモートで制御できるようにアプリを設定しました。すべての実験は、値とステータスとともに API に読み込まれます。アプリは、割り当てられた実験のバリアントを自動的にアクティブ化します。
フラグベースの機能制御
ユーザー、実験、機能が非常に多いため、リモートで制御する方がよいでしょう。Reddit はこれらの機能をリモートで制御するのに優れています。
アプリを起動するたびに、構成 API が呼び出され、400 を超える構成変数が読み込まれます。これらの変数に基づいて、さまざまな機能と機能のバリエーションが表示されます。
カルマの秘密
GetTopKarmaSubreddits
という操作名の API は、各サブレディットで獲得したカルマ ポイントとともにトップ サブレディットのリストを取得します。この API は、各サブレディットでのアクティビティから獲得したコメント数と投稿カルマ数を明らかにします。Reddit の Web およびモバイル UI 内でこの情報を見つけることができませんでした。
改善の範囲
API を読んで、どのような種類のデータを取得するのか調べているときに、 SubredditFeedElements
API は選択したサブレディットのフィードをロードしますが、各投稿にはサブレディットの詳細情報のネストされた JSON が含まれていることがわかりました。この情報は冗長であり、API のネットワーク負荷を軽減してパフォーマンスをさらに向上させるために削除できます。
注: SubredditFeedElements
API はSubredditFeedSdui
APIに置き換えられ、問題は修正されました。
AIを活用して洞察を得る
ChatGPT を使用して API から洞察を得ようとしました。そこで、すべての API とその curl および応答を含むファイルを作成しました。このファイルを CustomGPT にアップロードして、あらゆる種類のクエリを配置できるようにしました。API がどのような用途に使用できるか、応答の構造など、明らかな洞察が得られましたが、API が多すぎるためか、私がプロンプトの専門家ではないためか、多くの幻覚が見られました。AI によって得られた洞察の一部:
-
GetAllExperimentVariants
API — 多くの実験には、enabled
、variant_1
、control_model
、one_feed_ph_bridge_new_users
などのオプションを含む特定の「バリアント」名があります。このセグメンテーションは、Reddit が特定のユーザー セグメントで機能をテストして、その影響を判断していることを示しています。たとえば、実験d2x_avatar_in_comments_loggedin
は、loggedin
とloggedout
の 2 つのバリアントがあり、ユーザー認証状態に基づいて機能をテストしている可能性があります。 -
GetAllExperimentVariants
API — 実験には、ビデオ機能、広告配置、ユーザー インターフェースの強化、サードパーティ統合をカバーする幅広い機能テストを指すhybrid_video_rollout_android_v2
、active_sales
、gql_google_maps_integration
が含まれます。 -
GetAccountDetails
API — API レスポンスには、isSubredditCreationAllowed
、isNameEditable
、isPasswordSet
、ユーザーのモデレーターステータスなど、ユーザーのアカウントステータスの詳細を示すさまざまなフィールドが含まれています。さらに、アカウントが現在停止または制限されているかどうかを示すsuspensionExpiresAt
とisSuspended
含まれています。
API一覧
Reddit の仕組みを理解するために私が研究した GraphQL API のリストがあります。認証、レポートなどの他の API もいくつかありましたが、このリストには含めませんでした。
画面 | グラフQL API | 説明 |
---|---|---|
家 | すべての動的構成を取得する | アプリのさまざまな機能の動作に基づいて、400 を超える構成パラメータを読み込みます。構成は、JSON、浮動小数点数、文字列などの値のタイプとともに、一般的なキー値形式になっています。 |
| すべての実験バリアントを取得する | リクエストには、デバイスとアプリのバージョンを対象とした実験を割り当てるためのアプリとデバイスに関する情報が含まれます。レスポンスには、ID、実験名、バージョン、ステータスを含むすべての実験のリストが含まれます。 |
| アカウントを取得 | ログインしたユーザーの詳細をすべて読み込みます。 |
| ホームフィードSdui | ホームページに表示するために、最小限の詳細を含む最初のいくつかの投稿を読み込みます。 |
| フィード投稿詳細 (ID 別) | ユーザーが投稿をクリックした場合に備えて、すべての詳細を含む ID を使用して投稿をプリロードします。 |
| DiscoverBarのおすすめ | バーデータを発見します。 |
| ユーザープレミアムサブスクリプション | ユーザーのプレミアムサブスクリプションに関連するデータ |
| ユーザー広告適格性を取得する | ユーザーの広告適格性と設定を取得します。 |
| バッジカウント | ユーザーが獲得したバッジに関する情報。 |
| | |
サブレディットページ | サブレディットチャンネル | 説明、アイコン、カウンター、許可されている投稿タイプ、色など、コミュニティに関するすべての基本的な詳細を読み込みます。 |
| サブレディット分類トピック | コミュニティのカテゴリと表示テキストを読み込みます。たとえば、r/software コミュニティを読み込むと、ソフトウェアとアプリに #20 が表示されます。 |
| 招待保留中 | 名前が示すように、保留中の招待を確認しますが、どの招待かは正確にはわかりません。 |
| サブレディットチャンネル | サブレディットのチャットチャンネルを読み込みます。多くのサブレディットをチェックしましたが、見つかりませんでした。 |
| ブロックされたRedditors | ユーザーがブロックされている場合はデータを取得します。 |
| モデレーターを取得する | モッドのリストを取得します。 |
| 構造化スタイルとウィジェットの取得 | この API は、コミュニティのスタイル、ルール、詳細に関する情報を提供します。 |
| 関連コミュニティの推奨事項を取得 | この API は関連するコミュニティをもたらします。 |
| サブレディットミュート | サブレディットがミュートされているかどうかを確認します。 |
| サブレディットフィード要素 | サブレディットのフィードを読み込みます。サブレディットに選択されたフィルターとレイアウト オプションを取得します。フィードに表示される投稿に関するすべての詳細を取得します。 |
| 投稿情報IDコメント | このリクエストは最初の投稿のコメントのみをプリロードします。 |
| | |
投稿ページ | カスタム絵文字ステータスを取得する | この API はサブ Reddit ID で呼び出され、サブ Reddit のカスタム絵文字のステータスを読み込みます。この API が呼び出される理由はあまり明確ではありませんが、私は何度もこの API を目にしてきました。テストしたすべてのケースで、応答は |
| GetSubreddit実績フレアステータス | emoji status と同様に、サブ Reddit ID を取得し、 isEnabled: false として応答を取得します。 この目的は私にはわかりません。 |
| 投稿情報IDコメント | この API は、リクエストで渡された投稿 ID を使用して投稿のコメントを読み込むために使用されます。 |
| コメントページ広告 | コメントのすぐ上に広告を読み込みます。 |
| | |
プロフィールページ | RedditorByName | ログインしたユーザーのプロフィール詳細を読み込みます。 |
| 投稿セット設定 | 読み込む投稿の数。 |
| ゲットトップカルマサブレディット | 各コミュニティのカルマ ポイントを持つ上位のサブレディットのリストを取得します。この API は、各サブレディットでのアクティビティから獲得したコメントと投稿のカルマの数を明らかにします。 |
| ユーザープロフィールフィード | コメントと投稿を含むユーザー プロファイルのフィード。 |
| ユーザー公開トロフィー | リクエストで渡されたユーザー名が獲得した実績とトロフィーのリストが、ID、名前、画像とともに表示されます。 |
| TippingProfile移行済み | チッププロフィールの詳細。この機能はあまり使用していません。プロフィールに残高が 0 と表示されました😄。 |
結論
この分解実験の結論として、いくつかの点を指摘したいと思います。
- Reddit の API はあまり高速ではありませんが、代わりにプリロードを使用してユーザー エクスペリエンスを向上させます。
- API の作業は決して完了することはなく、Reddit のエンジニアでさえ、それをさらに改善するために取り組むべき作業がいくつかあります。
- アプリと実験の構成をリモートで維持することで、ユーザー エクスペリエンスを適切に制御できます。
- Requestly のエンジニアは、GraphQL リクエストごとに操作名を表示するという素晴らしい仕事をし、開発者の作業を大幅に楽にしました。