ブラウザ版NewsPicksのリアーキテクチャとABテスト手法と、そこから得た学び


# はじめに
こんにちは。NewsPicks エンジニアの鶴房です。
フロントエンドの刷新プロジェクトにおいて、主にインフラとバックエンドを担当しています。

現在NewsPicksでは、ブラウザ版の基盤を刷新(リアーキテクチャ & リニューアル)しています。
全く違う旧画面と新画面、全く違うそれぞれの画面において、ABテストを行いユーザーの反応を調べました。
今回は、その際に行ったことを記載していきます。

# 背景
冒頭で書いた通り、わたしたちは現在、ブラウザ版のNewsPicksの刷新 (リアーキテクチャ & リニューアル) を行っています。 
[番組トップページ](https://newspicks.com/programs/)/[特集トップページ](https://newspicks.com/series/)などいくつかのページをリニューアルした後、ついに目玉となる総合トップ(いわゆるトップページ)のリニューアルを行いました。以下のページです。

https://newspicks.com/

このリニューアルにつき、いくつかの大きな変更があるので、それらについて説明します。

### デザインの変更
まず、10年近く変わっていなかったデザインを変更しました。
以下の通り、デザイン的には、ほぼほぼ別のページとなっています。

旧総合トップ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581441/8588b969-1cc7-93cc-43e5-5c496fbf1d8a.png)

新総合トップ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581441/1856ffcd-918b-e75a-965f-99123cf090d6.png)

### アーキテクチャの変更
#### 旧総合トップ
旧総合トップにおいては、 「Spring + Thymeleaf + CoffeeScript + jQuery」 を用いて画面を描画してました。
2010年代前半においては妥当な技術選定かと思いますが、2023年も終わろうとしている今、この環境でフロントエンドの開発を続けていくのは厳しさがある、というのは多くのエンジニアが同意してくれることかと思います。
NewsPicks社内においても、触りたがる人が少ない、デバッグがしづらい、などの問題が起きていました。

NewsPicksにおいては、アプリの方が利用ユーザー数が多かったこともあり、ブラウザ版に関しては長らくこのままの状態でした。
今回、Webからの流入を増やすためリニューアルをするにあたり、技術的負債を解消しようということで、リアーキテクチャも行いました。

#### 新総合トップ
新総合トップにおいては、　 [Nextjs + React + graphql + TypeScript] を用いて画面を描画しています。
このリアーキテクチャによって、平均描画時間の低下、開発者体験の向上、開発速度の向上など、開発チームにおいては多くのメリットを享受することができました。(これはこれで面白いテーマなのですが、今回は詳述しません。)

一方で、先ほどのスクショの通り、画面のデザインを大きく変更したので、ユーザーにとってメリットがある状態であることは検証することが必要でした。

# ABテストの実施
前述の通り、開発者の体験や定量面(描画速度等)には多くのメリットが認めたれた今回のリニューアルですが、当然ながら、一番重要なことはユーザーに対してメリットを与えられているかどうかです。

ということで、新画面と旧画面を対象にABテストを行いました。
新画面で試したいパターンが２パターンあったので、
新画面A : 新画面B : 旧画面 で3:3:４ になるように振り分けをしました。

## 今回のABテストの特徴
一般的に、ABテストでは、ちょっとフォントの大きさを変えたり、画像サイズを変えたり、コンテンツの順番を入れ替えたり、など、見た目や印象に関与する、いわるるフロントエンド側に依るケースが多いと思います。

その場合は、サーバーでユーザーごとにABテスト結果の抽選をして、その結果に応じて描画を変更するようにすることでABテストを実施できます。

今回は、新総合トップを利用するユーザーと旧総合トップを利用するユーザーで全く違うサーバーに接続する必要があるため、サーバーだけでちょろっと描画を変えるだけではやりたいことが実現不可能です。

## ABテスト実施の詳細
Abテストの実施にあたって、利用した技術、注意したことなどを記載します。

### ELBの振り分け機能を利用

弊社ではAWSを利用しているので、ELBの振り分け機能を利用しました。

下記の通り、ELBではリクエストに特定のHttp Headerがついている場合のみ特定のターゲットグループにリクエストを振り分ける機能があります。

https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/listener-update-rules.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581441/fbd9ff36-664f-57e2-84cd-6c6fd07f67b8.png)

今回は、Cookie内に新総合トップに抽選された値を持つユーザーを、新総合トップにルーティングするルールを追加しました。
(尚、↑の例示ではHttp Headerとありますが、Cookieも一つのHttpHeaderなので、cookieによる振り分けは上記の方法でできます。)

具体的なルールで言うと、以下のような感じです。
```
パス =  "/" かつ
Header =  "cookie="*abTest=renewal*" の時
新総合トップのターゲットグループにフォーワーディングする
```

### Cookieを配布する
Cookieに基づいてルーティングする以上、各ブラウザに事前にCookieを配布しておく必要があります。

#### Cookieの配布処理の方法
全てのリクエストを対象に、当該Cookieがない場合に抽選してCookieを付与する処理をしています。
これによって、一度でもNewsPicksにアクセスしたことあるブラウザはCookieにABテストの識別子を持つことになります。
また、後からABテストの割合を変更したい場合やバグがあった場合に備えて、配布から24時間以上たったCookieに対しては、強制的に再抽選をして、Cookieを再度付与するようにしました。

#### Cookieの事前配布
ELBの切り替えを行う前に、Cookieの配布のみ行う期間を設けました。

これは、今回のケースでは、同一のURLに対してあまりにも画面が違いすぎるため、突然画面が切り替わってしまうユーザーを減らすための配慮です。
今回は、ELBでCookieを参照して振り分けを行う関係上、当該Cookieを持たないアクセスがきた場合、本来的に新総合トップにルーティングされるべきユーザーのものであっても、一度目は旧総合トップにルーティングされてしまいます。

そのユーザーは、その後更新ボタンを押したり、回遊して総合トップのパスに再びきた際に、今度は新総合トップが表示されることになります。

同じURLで全く違う画面が表示されてしまうため、短い時間でこの事象が発生した場合に非常にユーザー体験が悪いことが予想されます。
このことを回避するためにCookieの配布は事前に行い、ELBの切り替えは配布がおおよそ完了した後の深夜に行いました。

これにより大多数のユーザーで近接した時間軸で新旧の総合トップが両方出てしまう問題を回避しました。

### ログを揃える

ここまで書いてきた実装面の問題を解決して、ABテストを開始した後には、新旧を比較して検証を行うフェーズがあります。

ここで、滞在時間や、記事閲覧数、他ページへの遷移率、広告表示数など多彩なログをもとに、今回のリニューアルの評価を行います。

これらのログをログサーバーに送って保存しているのですが、ログのフォーマットを揃えておくと、分析するときに同じクエリを利用できるので便利です。

### ユーザーに元に戻す選択肢を与える
普段から使い慣れているユーザーに対して、いきなり画面が変わると体験が悪いだろうという仮説の元、元の画面に戻す機能を追加しました。

そのユーザーにとって使い慣れたサービスの画面を変更して、「ほら、論理的に考えてこっちの方が使いやすいでしょう？」と言うのは、お母さんが勝手に子供部屋を片付けて「綺麗になったしこっちの方が色々使いやすいじゃない？」と言うのと同じだ、と言うのが我々のチームの考えだったためです。

散らかっていた部屋であっても、利用者はどこに何があるかわかるから便利に感じていたのに、勝手に整理されたらわからなくなってしまいます。

そのポリシーに従って元に戻すボタンを実装しましたが、しかし、これが本当に必要なことであったかは、後述の振り返りの章で総括しようと思います。

# 結果
これらの対策をおこなった結果、スムーズにABテストを開始し、必要なログを取得することができました。

ABテストの結果としては、切り替えに伴いマイナスの有意差があるものがなく、その上でニュースをクリックして他ページへ遷移するなどのアクション率が向上した、というものでした。

開発チームにとってのメリットや、レスポンス速度、SEOの点数などの定性的なものに関しては新総合トップの方が優れていることが明白で、ABテストの結果としてもユーザーのアクション率向上が確認できたので、ABテストは成功と見做し、新総合トップを全体適用をしました。

# 振り返り

## やはりCookieはステートフルで辛い
巷では散々言われていることかと思いますが、ステートフルなものは管理が難しいです。

今回も、Cookieが原因で、意図しないページに行ってしまったユーザーがいました。
通常のABテストで意図しないページにルーティングされても、は統計に差し障りがあるだけで、さして問題ないと思いますが、NewsPicks的には大問題でした。

NewsPicksではNewsPicks Enterpriseというサービスがあります。
これは社内の閉じた空間で、NewsPicksを利用するためのもので、自社に関係のあるニュースなどを、たとえば部長がPICKしてコメントをつけ、それを社内で議論する、などの使い方がされていて、コミュニケーション活性化のために多くの企業で利用されています。

このサービスを利用しているユーザーに関しては、ABテスト対象外で、全員旧総合トップにルーティングされる手筈でした。

しかし、NewsPicks Enterprisのごくごく一部のユーザーで新総合トップが表示される、という報告を受けました。

この問題について、調査を行ったり再現を試みたりと原因究明に努力をしたのですが、恥ずかしながら原因はよく分かりませんでした。
(念のため補足すると、原因は不明なものの、対象ユーザーについてCookieを上書きするレスポンスを返す修正をすることで事象自体は解決しました。)

調査や再現に苦労した点として、
・前述した元に戻すボタン、NewsPicks Enterpriseのユーザー除外の他にも、このブログでは割愛した他の仕様などもあり、ABテストの抽選ロジックがかなり複雑化、肥大化してしまったこと。
・当該ユーザーにCookieを配布した当時のサーバーの状況を再現しないと、原因がわからない場合があること(今回はこれで、報告を受けた時に再現を試みると意図したCookieの値が返却され、再現できませんでした。)
・Cookieの配布後はユーザーのブラウザが管理しているため、その間に何があったかもよく分からない。

などがあげられます。

月並みな話になりますが、やはりステートフルなものが扱いが難しいので、なるべく管理しやすいように設計するのが重要であると思います。
今回でいえば、再抽選の頻度を上げることや、付与時に詳細なログを残すことが対策として考えられるでしょう。

尚、この新総合トップのリリース後、再びABテストを行なっているのですが、そこでは、リクエスト毎に抽選を行い、ステートレスな実装にしています。
調査の際の認知負荷が減るメリットが大きく、やはりステートレスな実装な良いものだと、再確認できました。


## 新旧でログを揃えることは良かった。
結果の集計処理をするときに、かなりのSQLクエリを書くことになりましたが、ログのフォーマットを揃えていたおかげで省力化できました。
全く違う画面であっても、同一のフォーマットでログを送ることは、データの継続性の面からも重要なことだと思います。

## 「元に戻す」機能は必要だったか？
前述の通り、普段から使い慣れているユーザーに対しての配慮として元に戻すボタンを配置しました。

どんなWebサービスであっても、リニューアルなどでレイアウトを変えると、辛辣なご意見をいただくものかと思います。
我々も例外ではなく、「画面がメチャクチャになってしまった。」「見たいものがどこにあるかわからない」等、いくつかの辛辣なご意見をいただきました。(想定していたよりかは少なかったです。)

そういったユーザーの方々には元に戻すボタンは有用であったと思います。

一方で、元に戻す機能をつけたことで、

・ABテストの複雑性が増え、実装工数もかかる。
・前述のCookieのステートフルな特性と相まって、特定のユーザーに対してどのCookieの値が配布されているのか分かりにくくなり、トラブル解決に時間がかかった。
・ログ集計の際に、「元に戻す」ボタンを押してABテストからドロップアウトしたユーザーの集計処理に非常に苦労した。(これに関してはデータ構造が悪い部分も多分にあると思います。)

などの好ましくない事象が生じました。

今回は、リニューアルの他に開発基盤の刷新も兼ねていたので、ABテストで有意に悪い結果が出ない限りは、新総合トップに切り替える方向で進めていましたし、実際に切り替えました。
旧コードをいつまでも保守するわけにもいかないので、「元に戻す」で古い画面を選んでくださったユーザーの方も(申し訳なく思いつつも、)最終的には新画面をご利用いただいています。

このことを考えると、「元に戻す」ボタンはABテスト期間中のある種の延命措置のようなものであったと評価できます。
それなりに工数もかかり、全体の複雑性も上がり、ログ集計などのオペレーションが混乱したりと、このことで発生したコストを考えると、必要な措置だったかは疑問が残ります。

今回、新画面A : 新画面B : 旧画面 で3:3:4 の比率でABテストを行いましたが、それで「元に戻す」ボタンをつけるくらいだったら、たとえば 0.5:0.5:9 でテストするとか、統計的に有意差を認められる最小限のユーザーでテストするなどした方が良かったのではないかと感じます。

これであれば、切り戻す場合であっても影響が最小限で済んだはずであると感じます。

# 終わりに

ABテストの話は以上になります。
この記事では未解決の問題も多いですが、私の経験を糧に、読者の皆様がより良い実装をされることを期待しております。

もっと良い方法等ありましたら、是非コメント等いただければと思います！

最後まで読んでいただきありがとうございました！