3月24日、サイバーエージェントのエンジニア・クリエイターによる技術カンファレンス「CyberAgent Developer Conference2022」を開催しました。本記事では「サイバーエージェントのフィーチャーフラグを活用した高速開発」の様子をお届けします。

 

目次
■フィーチャーフラグと開発
■フィーチャーフラグのメリット、デメリット
■社内フィーチャーフラグ基盤「Bucketeer」
■「Bucketeer」のユースケース
■「ABEMA」におけるフィーチャーフラグの活用方法
■フィーチャーフラグを管理する「Flagfit」
■まとめ

 

■フィーチャーフラグと開発

フィーチャーフラグとは、静的または動的に機能のON/OFFを切り替える手法で、コードで表すと以下のようになります。

 

 

 

 

 

 

 

もしフィーチャーフラグがtrueであれば何かをして、そうでなければ別の何かを行なうといったコードを書くことになります。フラグの値はON/OFFでなくても構いません。色や文言で返してあげることも可能です。例えば登録導線に対して、あるユーザーには「登録をお願いします」、別のユーザーには「登録をクリック」を表示するなど、アプリの挙動を変えることが可能です。フラグの値は2つ以上でも構いません。

フィーチャーフラグのユースケースとしては、限定的なリリース、トランクベース開発、A/Bテストなどが挙げられます。限定的なリリースとは、例えばベータユーザーやアルファユーザー、プレミアム登録ユーザーなど、ユーザー群に対してその数だけアプリの新バージョンをリリースするようなものを指します。有名なケースを挙げると「Uber」では、ユーザーごとに提供されている機能が異なります。

その他、段階的ロールアウトでも活用されています。例えば1%のユーザーにだけ新機能をリリースし、その結果を見てから段階的に100%リリースに進めるというものです、ロールバック、ロールアウトしている最中に問題が見つかれば、前のバージョンにロールバックということも可能になります。

トランクベース開発では、従来の開発の問題点である、開発ブランチで長い時間をかけてしまったがゆえに、マージの際にマージコンフリクトが起きやすくなり、レビューが非常に大変になるという問題を解決します。

フィーチャーフラグを使うことによって、開発している機能をOFFにしておき、そのままmasterにマージして、リリースまで進めていくことができます。

短いスパンでmasterブランチにマージすることによって、コンフリクトが起きにくく、レビューがしやすいプルリクエストを作ることが可能です。またA/Bテストでは、実際のユーザーで施策の効果を確かめながら開発することができます。

新機能を開発しても、それをユーザーが使ってくれるか、喜んでくれるかは実際にリリリースしてみないと分かりません。A/Bテストでは、前のバージョンと新しいバージョンをユーザーごとに出し分け、その結果から、どちらが良かったかを判断することが可能になります。

 

■フィーチャーフラグのメリット、デメリット

フィーチャーフラグの本質を一言で表すと、デプロイとリリースを切り離すということに尽きます。これによってリスクを最小限に抑えて高速な開発および本番環境でのテストが可能になります。結果的にストレスが少ない開発ができるようになりますし、ユーザーに対してより良い状態でサービスを提供することが可能になります。

一方、フィーチャーフラグのデメリットとしては、コード量が増えるということが挙げられます。具体的には、アプリに新しいバージョンと古いバージョンの複数の振る舞いがコードに載ることになります。

さらにフラグの管理コストもかかります。複数の機能でフィーチャーフラグを導入することで、フィーチャーフラグがその度に増え、最終的にどのフラグが実際に利用されているか分からなくなったり、フラグ同士が依存してしまったりといったことに対応するための管理コストがかかってきます。またフィーチャーフラグを使うシステムや、サードパーティツールの学習導入コストもデメリットといえるでしょう。

 

■社内フィーチャーフラグ基盤「Bucketeer」

現在サイバーエージェントでは、社内フィーチャーフラグ&A/Bテストプラットフォーム、通称「Bucketeer(バケティア)」の開発を行っています。「Bucketeer」は、2019年4月に新しい未来のテレビ「ABEMA」の基盤プロダクトとしてリリースしました。その後「Developer Productivity室」へ移管され、「ABEMA」以外のプロダクトへの導入を開始しています。

※サイバーエージェントは、開発者の生産性を向上をさせ、サービス開発を支える「Developer Productivity室」を2020年6月に設立しました。

「Bucketeer」では、フィーチャーフラグの機能を実現するために、クライアントSDKを開発しています。このクライアントSDK経由で、アプリが「Bucketeer」のサーバーにリクエストを投げ、サーバー側でユーザーのIDやユーザーの属性情報を見て、このユーザーはA、このユーザーはBなどと判定し、レスポンスとして返すというアーキテクチャになっています。

■「Bucketeer」のユースケース

ここからは「Bucketeer」の実際のユースケースについてご紹介していきます。

ターゲティング機能
開発者やQAなど限られたユーザーを対象に機能をONにしたいという要望がありました。これに対して「Bucketeer」では、特定のフィーチャーの値をどのユーザーに出すかを細かく決めることが出来る、ターゲティング機能を追加しました。

上記の例では、foo、hogeといったユーザーに対してはtrueを返し、feeユーザーにはfalseになるといった細かい設定ができます。この機能によって実際に開発をしている開発者やQAを行う人にはフィーチャーをONにしておき、その他の一般ユーザーに対しては機能をOFFにしておくといったことが可能になります。

ルールの設定
任意のアプリバージョンのみ機能をONにしたいという要望に対しては、ルールを設定しました。

こちらの例では、アプリのapp_versionが1.21.4または1.22.0以上であればtrueになるといったことを、2つのルールを掛け合わせることで可能にしています。

自動オペレーション機能
決められた日時にリリースしたいという要望がありました。すでにアプリのデプロイが終わっていて、実際に新しい機能のリリース発表や、希望した日時に合わせて機能をリリースして、ユーザーが使えるようにしたいということでした。

これに対しては、自動オペレーション機能を搭載しました。例えば、2022年1月25日0時00分にフィーチャーフラグが有効になります。この機能によって、ユーザーのアプリにtrueが返却され機能がONになります。

自動的な機能OFF
また、障害時に自動的に機能をOFFにしたいという要望がありました。これはアプリでエラーを感知した際、ある一定のエラーレートを超えた場合にその機能をOFFにするものです。

この機能では、アプリ側で何かエラーが起きた時に「Bucketeer」に対してエラーイベントを送信します。「Bucketeer」側で一定のインターバルの中でエラーレートを計算して、そのエラーレートがある設定した閾値を超えた時にフラグをOFFにします。アプリはある一定の期間でフラグ値を「Bucketeer」にリクエストを投げて更新しているので、次のリクエストの時に新しいフラグの値が返却されてそれがOFFで返ってくるようになれば、機能がOFFになります。これを自動的に行うのです。

変更の即時反映
フィーチャーフラグの変更を即時に反映させたいという要望がありました。通常、アプリ側のフィーチャーフラグはアプリ開発者がSDKの初期化時点で設定したインターバルごとに更新されます。SDKは設定されたインターバルの間隔でサーバーから最新のフィーチャーフラグの値を取得しローカルにキャッシュします。例えばインターバルを10分に設定していた場合、上記の「自動的な機能OFF」でエラーを検知しフラグを自動的にOFFにしたとしても、実際のアプリで問題の機能が無効になるまでは最大10分の時間がかかります。その間にアプリ側でエラーが多発し、ユーザーが離れていってしまいます。、フィーチャーフラグ変更の即時反映はそういった場合に有効になります。

この機能はFCM、FirebaseのFCMを使って実現しています。アプリ側でエラーレートが高くなった場合に「Bucketeer」でフィーチャーフラグが先ほどの自動オペレーションや、コンソールのUIからフィーチャーフラグを変更する際に、自動的にFCMのプッシュ通知リクエストを送ります。Firebaseがプッシュ通知リクエストを受け取り、アプリ側にFCMのプッシュを送り、それを受け取ったアプリが即時に「Bucketeer」に新しいフラグを要求するリクエストを投げることで「Bucketeer」が新しいフラグ値を変更、返却します。この機能により、数秒でフラグ値の更新・変更が可能になりました。

 

SDKのリリース
その他の要望としては、サーバーサイドでも「Bucketeer」を導入したいといった要望がありました。これに対し、Go SDKや、最近ではNode.js ドSDKを新しくリリースしました。

 

Webhook API
外部モニタリングシステムからフラグ値の変更をしたい、例えばDatadogや、他のサードパーティのツールでモニタリングしている場合、そこでアプリのエラーや、不具合を検知してフラグをOFFにしたり値を変えたりしたいという要望がありました。そこで、Webhook APIを開発しました。これにより、Webhookを登録して自動的にモニタリングシステムから「Bucketeer」にリクエストを送ってフラグを変更することを可能にしています。

 

Flag Dependency
最後に、フラグAがtrueの時、フラグBもtrueにしたい、フラグBがフラグAに依存しているというような状態を作りたいといった要望がありました。これもFlag Dependencyという機能で開発し、順次リリース予定となっています。

■「ABEMA」におけるフィーチャーフラグの活用方法

ここからは、「ABEMA」で実際に利用されているフィーチャーフラグの一部を紹介します。

例えばON/OFFのフラグについては、応援機能や「ABEMA PPV ONLINE LIVE」をON/OFFする際に使われています。またパーソナライズ広告配信フォールバック有効期間、これはON/OFFではなく、有効期間を何秒何時間というふうにアプリ側に返すといったように使われています。

他にも、CMごとのタイムアウトを秒で返したり、新着訴求ポップアップのON/OFFであったり、アンケート再表示ロジックなどに使われています。アンケート再表示ロジックでは、ユーザーにアンケートをお願いする際、未回答ユーザーに短いスパンで複数回表示をしてしまうなど、ユーザーのUXが下がることに繋がるため、いくつかの再表示の可否、日付、回数などをルールに複雑に組み込み、最適な表示ロジックをフィーチャーフラグによって実現しています。

次に運用面についてです。「ABEMA」では、これまで300以上のフィーチャーフラグが使用されています。

「ABEMA」の運用では、リリース前はフラグを必ずOFFにしておきます。ただし、デバッグやテストなどの際には、自動的にONにして開発している機能を開発者やQAエンジニアが見れるような仕組みとなっています。また、リリース直前にフラグをONにして動的に変更できるようにもしています。さらに、リリース後ロールアウトを行った後、使用しなくなったフラグを削除するといった、フィーチャーフラグのライフサイクルを管理しています。

■フィーチャーフラグを管理する「Flagfit」

「Flagfit」は「ABEMA」で開発したフィーチャーフラグを管理するためのAndroid用クライアントライブラリで、OSSとして公開されています。

Flagfit – GitHub
https://github.com/abema/flagfit

「Flagfit」の特徴として、フラグをkotlin interfaceとして扱うことができます。また、アノテーションを使用して統一したインターフェイスでフラグ管理が可能になります。これにより、フラグを安全に管理することができます。iOSも同様の仕組みで実装されています。

下記は「Flagfit」を使用したフィーチャーフラグのコーディングの一例です。

このようにアノテーションを使ってフィーチャーフラグを管理しています。

例えば、ひとつの使い方として、WorkInProgressというアノテーションがあります。これはアノテーションがついているファンクションは必ずfalseが返却されます。

また、Experimentというフラグでは、Experimentのフラグソースに指定したフィーチャーフラグのシステムから実際に値が返されます。
他にも、デバッグ時にフラグの値を任意にしたり、テスト時はローカルで設定した値を使用したりすることも可能です。さらに新しくカスタムアノテーションを定義することもできます。このように「Flagfit」を使うことによって、もしフィーチャーフラグのデータソースを複数持っていたとしても同じインターフェイスで開発が行えるようになっています。

■まとめ

フィーチャーフラグは、デプロイとリリースを切り離すことによって、リスクを最小限に抑えて高速な開発と、本番環境でのテストを実現します。また、フィーチャーフラグはアプリの挙動を変えることができるため、最終的にユーザーのコンバージョンを見ることができ、A/Bテスト、もしくはA/Bnテストが可能になります。フィーチャーフラグを使うことによって、マージコンフリクトが起きにくく、PRのレビューがしやすい開発、トランクベース開発など、ストレスが少ない開発が可能になります。

「CyberAgent Developer Conference 2022」のアーカイブ動画・登壇資料は公式サイトにて公開しています。ぜひご覧ください。


https://cadc.cyberagent.co.jp/2022/

 

■採用情報

新卒採用:https://www.cyberagent.co.jp/careers/special/students/tech/?ver=2023-1.0.0

キャリア採用:https://www.cyberagent.co.jp/careers/professional/