アジェンダ

李志鑫氏:はじめまして、李志鑫と申します。CSI Dev Bチームでサーバーサイドエンジニアをしています。また、Home Server Devチームでは、LINEアプリケーションのホームタブのサーバー開発をしています。今日は、LINEのホームタブに情報を配信するために使える汎用性の高いシステムについて、お話ししたいと思います。

今日のテーマについてです。まずLINEのホームタブとは何か。その中にあるレコメンデーションコンポーネントについてお話しします。そしてこの配信システムをどのように実現しているのか、システムのアーキテクチャや使用している技術についてお話しします。

次に、私たちが遭遇したサーバーの課題と、それを克服するための戦略に焦点を当てたいと思います。最後に、2つの応用事例について紹介します。

LINEのホームタブとは

みなさん、LINEアプリケーションを使っている方でしたら、ホームタブはご存じだと思います。LINEアプリケーションの一番左のタブです。ここにはユーザープロフィール、設定、通知アイコン、友だちとグループ、ユーザーがホームタブでカスタマイズできるサービスリストなど、いくつか重要なコンポーネントがあります。

サービスリストの下にある「おすすめのコンテンツ」が今日のトピックです。ユーザーはさまざまなレコメンデーションコンテンツを得られます。例えば日本のユーザー向けには、おすすめスタンプ、無料マンガ、オープンチャット、お得なキャンペーン、音楽・ライブ配信など、さまざまなコンテンツをLINEアプリで確認できます。

しかし、レコメンデーションコンテンツは、数が多いだけではなく、レイアウトも異なります。スタンプでは画像の周りにタイトルが表示されていますが、マンガでは画像の割合が異なります。また、オープンチャットでは、画像の周りにグループ名やグループ番号を表示しています。これらのコンテンツをそれぞれ別のレイアウトで作成するには、どうすればよいのでしょうか。

レコメンデーションコンテンツを作る共通の流れ

まず、レコメンデーションコンテンツを作る共通の流れとして、通常は3つのステップを設けています。デザイン、開発、検証・リリースです。

デザインの段階では、表示コンテンツのトレンドやフィーチャーを元に、デザイナーがレコメンデーションコンテンツのUIを作ります。

開発の部分では、iOS・Androidチームメンバーが現行のバージョンのUIを実装します。また、ホームサーバーはクライアント用のAPIサーバーで、APIにレスポンスデータを追加します。

データプロバイダーは、ホームサーバーの上流に位置するサーバーです。機械学習によるレコメンデーション技術を用いて、ユーザーごとのレコメンデーションデータを提供します。レコメンデーションAPIは、コンテンツごとに実装する必要があります。

また、スマートチャンネルは、パーソナライズされたレコメンデーションのためのLINEの内部サービスで、ほとんどの地域でこれを使用しています。

すべての開発が終わった後、QAメンバーがUIターゲットやコンテンツ情報の検証を行い、企画チームが最終的なリリースの日程を決定します。

このシステムのいくつかの欠点

さて、一般的な開発の流れから、実はいくつかの欠点が見えてきました。1つ目は、新しいレコメンデーションコンテンツの開発コストはかなり高くなっています。1つのコンテンツにつき3つの異なる開発チームが関わるからです。また、コンテンツごとに繰り返し作業を行う必要もあります。

2つ目は、クライアントサイドでUIを実装しているため、新しいコンテンツが出るとモバイルアプリケーションの新しいバージョンが必要になるなど、開発のリリースサイクルが遅くなることです。そして3つ目は、リリースされたコンテンツのUIは変更できないという点です。

となると、この欠点を克服し、より汎用性の高いシステムにするにはどうしたらいいのか、という疑問が湧きます。実際の実装の話をする前に、システムに求められる条件をいくつか挙げておきたいと思います。

1つ目はこのセッションのタイトルどおり、汎用性です。クライアント側には、ハードコーディングされたUIはこの観点から見るとあまり望ましくないです。新しいコンテンツに対してハードコーディングが必要ない実装を出来るならクライアントバージョンを上げなくてもリリースできます。

2つ目は反復コストの削減ですが、新しいシステムでは、クライアントの開発コストをなくし、ホームサーバーアプリケーションの開発も基本的な設定だけで済むようにしたい、と考えています。

3つ目は、LINEは世界中にユーザーがいるので、サーバーサイドで多言語テキストをサポートしたいと考えました。

この3つの条件を満たすことができれば、次のようなシンプルな開発フローが可能になります。設計ができたら開発が必要なところが1箇となり、そのあとの検証とリリースをするだけで終わります。

技術とシステムアーキテクチャ

続いて適用した技術とシステムアーキテクチャの部分に入っていきたいと思います。最初に、UIのハードコーディングの代わりに使おうと思った技術は、Flex Messageです。ご存知の方がいるかもしれませんが、これはLINE Messaging APIの機能です。

LINE Messaging APIを利用することでLINE公式アカウントからメッセージを送信できます。Flex MessageはJSON形式のテキストで、レイアウトをHTMLのように変更できることにより、各コンポーネントがきれいに表示されます。

このように、Messaging APIを使ってLINEのボットを作成し、Flex Messageを送信します。Flex Messageのレンダリングエンジンがクライアントの内部機能であり、メッセージがユーザーの端末に届いた後にレンダリングされて画面に表示されます。レンダリングされた結果の例としては、次の「Brown Storeレシート」や「Brown Cafeカードメッセージ」をご覧ください。

しかしJSONのFlex Messageの技術だけでは、ホームタブのレコメンデーションコンテンツフォーマットとしてのニーズに合いません。Flex Messageの仕様の変更については、後でお話しします。

レコメンデーションシステムの流れ

ここからはレコメンデーションシステムの流れを紹介したいと思います。ユーザーがLINEアプリケーションを開くと、クライアントはホームサーバーからレコメンデーションデータを要求します。

もちろんホームサーバーはレコメンデーションデータを持っていません。そこで、データ提供者であるアップストリームサーバーに、rawのレコメンデーションデータを依頼します。

レコメンデーションデータを取得したら、ホームタブサーバーがFlex JSONを生成します。これはFlex Messageと似ていますが、ホームタブに適したものです。このステップをServer-side templatingと呼んでいます。サーバーがクライアントにその出力となるFlex JSONを返信します。最終ステップはクライアント側でFlex JSONをレンダリングした結果をユーザーに表示します。

フローの詳細

それではフローの詳細を見ていきましょう。ここではデータプロバイダーからのレスポンスの例を示します。コンテンツの種類と各項目のリスト、タイトル、画像URL、リンクURLなどの情報が含まれていることがわかります。

コンテンツの種類に基づいて、ホームサーバー内でFlex Templateを事前に定義しています。Flex TemplateはJSONのようなテキストですが、内部にはプレースホルダーのパラメーターがあります。UIとしてFlex Templateは空のタイトルと画像、そしてメインタイトルを入れるべきプレースホルダーであると想像できます。

実際のデータと組み合わせます。サーバーはこのデータをFlex Templateに注入し、最終的なFlex JSONを生成します。例えば「ムーンとジェームズ」のタイトルはFlex Templateのタイトルパラメーターで置き換えられ、最終的にJSONが生成されます。

最終的に生成された結果をクライアントが受け取ると、それが実際のクライアントのUIにレンダリングされます。

ここでシステムフローで示されたFlex Templateについて詳しく紹介したいと思います。Flex TemplateはFlex Messageを改良したものです。元となるFlex Messageと比較すると、サーバー側とクライアント側の両方でホームタブのレコメンデーションに合わせて多くの機能を持っています。

サーバー側では、多言語に対応するために、ローカライズされたテキスト機能、パラメーターの代用、サーバー側のプロパティのカスタマイズを追加しています。iOSやAndroidの場合にはLINEのテーマ(着せかえ)やダークモードのカラーマッチングなどがあります。

また、ユーザーのプロファイルを表示するために、ユーザープロフィールと名前の表示をサポートしています。また、Flex Templateには、縦型リストなどのバブル以外のレイアウトが追加されています。

その機能の例を紹介したいと思います。ここではローカライズされたテキストのための特別なパラメーターを定義しています。「hometab.recommend.common.seemore」です。レコメンデーションコンテンツを要求するユーザーの実際の言語に基づいて、サーバーは適切な言語のテキストを選択します。例えば「see more」を英語、日本語、中国語で表示できます。

APIパラメーターの代用です。先ほどお話ししたとおり、ここではいくつかのパラメーターをプレースホルダーとして定義します。サーバーは、テンプレーティング処理の途中でAPIレスポンスから情報を取得し、それらをテンプレートに入れます。そして、アップストリームプロバイダーのAPIレスポンスから、実際のタイトルを取得します。

もう1つはサーバーサイドのプロパティのカスタマイズ機能があります。これにより、いくつかのプロパティをサーバーサイドで制御できます。カスタマイズされたプロパティは、データベースに保存されますが、これはAPIレスポンスからではありません。

これらのパラメーターは、サーバーのテンプレート化の中間的な段階で入力されます。「seemore」のURLのように、サーバー側で管理したいと考えており、レコメンデーションデータの種類に応じて、異なる構成に置き換えられます。

そして最後がカラーマッチングです。クライアント側では着せかえごとにカラーキーを定義しています。例えば配置・タイトルにはプライマリーカラーを使用し、他にはセカンダリーカラーということもあります。

クライアントの設定に基づいてダークモードのようなテーマ、もう少し明るいテーマ、あるいは別のテーマなどに合わせて色がかなり変わります。

システム導入時に発生した課題

システムフローを見たところ、導入する時にいくつか課題がありました。これが現在のホームタブの状況です。およそ56種類のレコメンデーションコンテンツがあります。サーバーからのリクエストは通常1秒間に約25,000です。また、スタンプ、ミュージック、テーマ、オープンチャットなど1日に合計約5,000万のコンテンツを提供しています。

サーバーのトラフィックは決して少ないものではありません。かなりのトラフィックボリュームを想定しなくてはなりません。また、ユーザーがいつでもレコメンデーションデータを取得できないと困るため、負荷を抑える戦略を実行しました。

それが、Expiration Control、Server Fallback、Retry Control、そしてCachingです。2020年、日本のユーザー向けにシステムをリリースしましたが、地震後に多くのユーザーが同時にホームタブにアクセスすることがあり、この時にはサーバーの負荷が高くなって、一部のユーザーにホームレコメンデーションを提供できませんでした。

問題解決のための4つの戦略

それでは、これらの問題を解決するために、徐々に追加した戦略を、それぞれ紹介しましょう。

まずExpiration Controlです。これはサーバーが、クライアントが次に新しいレコメンデーションコンテンツを要求するまでの待ち時間をコントロールできるということを意味します。そのため、レスポンスが成功するたびに、サーバーはレスポンスのJSONとともに、Expiration timestampを入れます。

クライアントはそのtimestampに基づいて、ユーザーに表示中のコンテンツをexpireすることや、新しいコンテンツをリクエストします。ここではデフォルトの時間として1時間を使用しているので、各コンテンツは1時間表示されますが、サーバーのトラフィックに応じてtimestampを制御できます。

次はサーバーのFallbackです。これはサーバーが1つのプライマリーデータプロバイダーからレコメンデーションの取得に失敗した場合に利用するための機能です。

我々は、リライアビリティの高いデータプロバイダーをFallbackとして使用しています。プライマリーのデータプロバイダーが、一時的にネットワークの問題を抱えていたり、新しいユーザーに対してのパーソナライズされたデータを取得できない場合がありあまして、その際に、Fallbackデータプロバイダーを利用します。

このケースはそれほどパーソナライズされたデータではありませんが、常になんらかのデータを提供できるのものです。スマートチャンネルの人はコンテンツが充実しているので、そちらをメインにしています。

そしてRetry Controlです。失敗レスポンスでは、クライアントが次のリクエストするまでの待ち時間を、サーバー側でコントロールできるものがあります。

ネットワークの問題や内部サーバーのエラーなどが発生すると、サーバーはfailureレスポンスにtimestampを追加します。これは、クライアントが再試行のタイミングを決めるために使用されます。また、リクエストタイムアウトの場合、クライアントはデフォルトの待ち時間を使用します。

そのため、サーバーが取得に失敗した場合、1分後に再試行して、サーバーがエラーから回復した場合は、その後問題なくレスポンスを返します。

次はCachingです。サーバーはテンプレートデータのローカルキャッシュを持っています。これはデータベースの要求にかかる時間を短縮するために使用されます。また、コンテンツ固有のプロパティを事前に処理できるため、サーバー側のプロパティカスタマイズの処理時間も短縮されます。

システムを使った2つの事例

最後に、このシステムを使った2つの事例をご紹介します。1つ目は、台湾のユーザー向けにパーソナライズされたレコメンデーションデータを公開しました。このパーソナライズされたコンテンツは、2020年に日本のユーザーに公開して、2021年に台湾のユーザーにも提供し始めました。これでパーソナライズされたコンテンツの範囲を広げています。

台湾ユーザー向けの15種類の新しいコンテンツを用意することは2ヶ月で開発・リリースしました。プロジェクト期間中はホームサーバーとクライアントの開発には、わずかな手間しかかかりませんでした。

これが台湾リリースの全体スケジュールです。パーソナライズされたデータプロバイダーの開発に多くの時間を使い、サーバー側のコンフィギュレーション設定やQA、リリースは半分の時間であることがわかります。フロントエンドでUIを使用すると、この実装よりもはるかに時間がかかります。

そして2つ目は、キャンペーンコンテンツの配信です。ホリデーコンテンツのような特殊な状況では、短期間だけユーザーに静的なコンテンツを提供したい、ということがあります。我々のシステムでは、このようなコンテンツをFlex Templateで提供できる機能も実装しています。

そのため、データ提供者、開発の負担をゼロにできます。例えばホリデーなどに特別な「おすすめ」をします。もちろん通常のレコメンデーションを上書きするようなコンテンツも設定できます。

将来的にはこのシステムを使って、よりよい魅力的なレコメンデーションコンテンツをユーザーに提供していきたいと考えています。ご清聴ありがとうございました。