はじめに
株式会社サイバーエージェントの「2weeks Web フロントエンドエンジニア向け体験型インターンシップ」にて、株式会社 WinTicket で 2 週間の就業型インターンに参加しました。
配属先は WINTICKET の Web フロントエンドを開発する Web チームでした。
定例 MTG やランチなどメンバー同士の距離が近く、馴染みやすい雰囲気が印象に残りました。
概要
インターンシップの期間は、8/6(水) から 8/19(火) までの 2 週間でした。
しかし、祝日(山の日)が含まれていたため、実働は 9 日間という非常にタイトなスケジュールでした。
初日に伝えられた想定実装期間はなんと 3 日間!
トレーナーの手助けによってキャッチアップや設計を効率よく進めることで、実際には 4 日半ほど確保できました。それでも振り返ってみるとギリギリ……。
やったこと
インターンのタスクと目標決め
最初にタスクの候補をいくつか提示されつつ、初日から 2 日目にかけてトレーナーと相談しながら決定しました。
普段から他社でアルバイトとして就業していることから、Web 実装というよりも基盤系のことをやりたいという希望のもとで絞り込んでいきました。
今回は、SSR と CDN キャッシュを両立した A/B テストの実施基盤について、検討・設計から実装までやってみることになります。
WINTICKET では、すでにバックエンド主導の A/B テストが導入されていましたが、いくつかの課題を抱えていました。例えば、Server/App チームとの連携が必要であったり、A/B 対象が CSR 部分に限定されたりといった点です。
そこで、Web フロントエンド単体で完結する A/B テスト基盤を構築することで、高速な PDCA サイクルを実現し、UX の継続的な改善を行える体制の整備を目指しました。
タスク決めと並行して、本インターンにおける目標設計も行いました。
事前に自身で決定した「終了時の理想状態」・「現状」に沿って、状態目標を「課題発見解決力・思考力」「資産化・提案力」「コミュニケーション」の 3 つの軸で設計しました。
今回は「未知のコードベースの理解」や「利害関係者との相談」などを重点に据えた目標を設定し、中間・最終の 2 回に渡って振り返りを行いました。
社内ドキュメント上で仕様・設計を検討
ゴールを決めたのち、社内ドキュメントツール上で仕様・設計を検討しました。
WINTICKET の Web フロントエンドは、Cloud Run で構成されたオリジンサーバー で React を SSR し、Fastly Compute を用いた CDN で SSR 結果をキャッシュする構成になっています。
SSR の結果は CDN にキャッシュされる
SSR 結果を CDN にキャッシュする際、ユーザー固有の情報が含まれてしまうのを防ぐため、一部のページやエンドポイント(Cache-Control: private
が指定されている)を除き、オリジンサーバーからユーザー情報にアクセスできない制限があります。
しかし、今回の A/B テストではユーザー ID を用いた出し分けを行うため、ユーザー情報にアクセスする必要があります。
そこで、Fastly Compute にてユーザー ID を取得し、Feature Flag SaaS に問い合わせて A/B テストフラグの値を決定してから Origin にて SSR を行う構成としました。
CDN から Feature Flag SaaS に問い合わせてフラグの値を決定する
処理の流れは以下の通りです。
-
CDN でユーザー ID を取得
-
Feature Flag SaaS に問い合わせて A/B テストフラグの値を決定
-
フラグ判定結果を
X-Flags
ヘッダーに格納し、オリジンサーバーへリクエストを転送 -
X-Flags
の結果をもとにオリジンで SSR -
Origin は
X-Flags
をそのまま返し、Vary
ヘッダーにX-Flags
を含める -
CDN でフラグ判定結果ごとに SSR レスポンスをキャッシュ
この設計により、CDN におけるキャッシュヒット率の大幅な低下を避けつつ、SSR 環境下での A/B テストを実現しました。
設計が一通り固まった段階で、概要を Design Doc としてリポジトリに commit し、いよいよ実装へと移行しました。
ユニットテストと格闘しながら実装
実装は、Feature Flag を用いて既存のコードベースと分離した状態で行いました。
インターン期間中に自身の変更がリリースに含まれる場面もあり、本番環境で動くコードを開発しているという緊張感と責任感を常に感じていました。
目標にしていた「未知のコードベースの理解」については、トレーナーの助言を得ながら幅広いコードを読むことができ、綺麗に整備されたコードベースに感動しながら多くの学びを得ました。
今回のタスクでは、あまり前例が多いとは言えない技術スタックの上で設計・実装する場面もあり、未知のライブラリと向き合う時間が大多数でした。
これに対して、ドキュメントや実際の実装を確認しながらトレーナーと相談できたのがとてもよかったです。
また、実装の中で、現在進行系で環境を移行中の箇所を触ることがあり、トレーナー以外の人にも相談・共有しながら実装を進めていきました。
コードレビューでは、テストの容易性や設計の観点からたくさんの改善提案をいただきました。
実践を踏まえて「良いコード」をたくさん吸収したことで、とても成長できたと実感しています!
学び
仕様の検討から設計・実装まで一連の流れを体験できた
今回の課題が「やりたいこと」ベースだったので、実際に仕様を検討する段階から主体的に進めることができました。
細かな意思決定を繰り返す場面では、自分の中で結論を出したうえで根拠や対案とともにトレーナーに相談することで、迷いなく進めることができていました。
先に考慮しておくべきだった箇所があとから見つかったこともありましたが、随時アップデートしながら仕様・設計を確実なものにできました!
過去の検討・設計をドキュメントとして残すありがたみ
今回の A/B フラグの仕組みは、特に X-Flags
ヘッダーを中心とした CDN・Origin 連携において、既存の Feature Flag の仕組みを拡張しながら統合することで実現しています。
既存の仕組みに新たな拡張を加える際には、既存の仕組みのことを深く知る必要があります。
社内ドキュメントツールに Feature Flag や Web 全体のインフラ構成について詳細に記載されており、キャッチアップを迅速に行うことができました。
これにより、自分が書くドキュメントも将来的にキャッチアップのために参照されるかもしれない前提で、将来を見据えた書き方を意識していました。
ユニットテストを整備する大切さ
コードベース全般を通して、ユニットテストがかなり整備されていました。思えば半分以上の時間は不慣れなユニットテストと格闘していた気がします。
ユニットテストのおかげで、自分の変更が意図しない箇所での挙動変更を引き起こしていないことを確認しながら進めることができたので、とても助かりました。
短い実装時間の中でも、設計の綺麗さやテストのしやすさにはこだわりを持って実装・レビューいただいていました。
どうしてもテストを綺麗に書けず、最終日前日に思い切って方針転換したところ、設計としても良いコードになり感動しました。
ユニットテストをしやすいコードは、結果的に良い設計になるのだなぁと思いました。
まとめ
トレーナー・メンターとして手厚くサポートしてくださった零さんをはじめ、Web チームの皆さん、そして関わってくださったすべての方々に、この場を借りて感謝したいと思います。
この 2 週間は、非常に濃密で、あっという間の時間でした。普段の個人開発では意識できていなかった多くの視点や、新たな知識に触れることができ、エンジニアとして大きく成長できたと感じています。
本当に、ありがとうございました!
Views: 0