フロントエンドから見た GMO Developers Day

2022年12月6日(火)~7日(水)の2日間、開発者向けテックカンファレンス「GMO Developers Day(DevDay)2022」が開催されました。ご来場頂いた方、またオンラインでご参加された方、ありがとうございました。

今回わたしはフロントエンドとして配信ページの実装を担当いたしましたが、運営・デザイナーからの要望、負荷などを加味しながら実装する上で工夫したこと、また今年残った課題について書いていきたいと思います。

フロントエンドが関わる部分

毎年イベントの仕様自体が変わるのですが、今年はオフライン開催(会場参加)とオンライン開催(ブラウザで視聴)を同時開催することになりました。

そのため、Webページもオフライン参加・オンライン参加両方に関して記載、オンライン参加のための配信ページを作成しました。
また、イベント中に告知されるキーワードを入力してスコアを取得・スコアに応じて景品が貰えるというキャンペーンを実施するため、キーワードの入力・スコア表示するためのページを作成しました。

設計

ディレクトリ

DevDay 自体は2020年から開催されており、今年の実装と同時に2020年と2021年の集客ページのアーカイブ化をしてほしいという依頼がありました。
また、イベント開催前・開催中・終了後でコンテンツが変わり、なおかつ短期間で確認とライブアップを繰り返す必要があることから、DevDay のトップページ developersday/ 配下に各年ディレクトリを作成、developersday/ から各年のトップページを読みに行くような設計にしました。

developersday/  ... developersday/2022/ 配下のファイルをインクルードするだけ
├ 2020/         ... 別ドメイン配下にあったページを移設
├ 2021/         ... developersday/ 直下にあったページを移動
├ 2022/
│ ├ index.php   ... トップページ(申込フォームなど)
│ ├ broadcast/  ... 配信ページ
│ ├ comingsoon/ ... 集客が始まる前にトップページに表示する Coming soon ページ
│ ├ devhunters/ ... キーワード入力キャンペーン用のページ
│ └ login/      ... ログインページ
├ broadcast/    ... developersday/2022/broadcast/ 配下のファイルをインクルードするだけ
└ login/        ... developersday/2022/login/ 配下のファイルをインクルードするだけ
  • 集客が始まる前の developersday/ は comingsoon を表示
<?php include_once '~/developersday/2022/comingsoon/index.php'; ?>
  • 集客が始まった後の developersday/ はトップページを表示
<?php include_once '~/developersday/2022/index.php'; ?>
  • 来年以降
<?php include_once '~/developersday/2023/index.php'; ?>

2022/ 配下には社内閲覧のみ可能な制限を入れたので、トップページには Coming soon を表示しつつ、社内からは 2022/ 配下にアクセスすれば集客開始後のページの確認ができるなど、現在の表示と次のライブ確認が重なるような案件でおすすめの設計です。

また、今回2021年のページが developersday/ 直下にあったためアーカイブ化で移動が必要でしたが、次年は次年のディレクトリをインクルードすれば良いだけなので移動の手間が省けます。

DBにアクセスしない

developers.gmo.jp は CMS がインストールされているので、運営チームがセッションのデータを入力したり、エンジニアを挟まずページを更新したりするのに利用しています。
しかし後述の配信ページなどはリアルタイムにデータを取得する必要があり、その度に DB にデータを取りに行くと負荷がかかりすぎる可能性がありました(実際サーバーダウンしたこともありました)。

なので DB を介さずデータを取得するため、任意のタイミングで DB のデータを Json に書き込み、データは Json に取りに行くという仕組みにしました。

タイムテーブルのセッションをクリックするとモーダルが開いて詳細が見られるのですが、これも Json ファイルのデータを読んでいます。最初は DB に取りに行っていたのですが、Json に切り替えたことでモーダルが表示されるまでの時間も体感1~2秒早くなりました

配信ページ

一番仕様が複雑だったのは配信ページでした。

  • 去年リリース直前で問題が発生したので、事前に本番環境で動作確認がしたい
  • 2トラックを並行配信、タブで切り替えられる
  • イベント開催前・開催中・開催後でコンテンツが変わる
  • リアルタイムに現在配信中のセッション情報が表示される
  • セッション中、配信終了直前にアンケートを表示する
  • 各セッションが終了するとアーカイブに移動、アーカイブタブから視聴・アンケートに回答できるようになる

事前の動作確認

配信ページはイベント開催前は「Coming soon」を表示させる仕様だったのですが、同時に開催中の配信画面の動作確認を行いたいというのが依頼者の希望でした。

こちらに関しては前述の通り、developersday/broadcast/ では developersday/2022/broadcast/comingsoon/ をインクルードし、社内のみ developersday/2022/broadcast/ にアクセス許可することでエンドユーザーに配信画面を見せることなく動作確認が可能となりました。

2トラックを並行配信

今年はオフラインセッション(会場でリアルタイムに開催される対談)= TrackAオンラインセッション(事前に録画した動画を配信)= TrackB の2トラックが並行配信されたため、配信画面で切り替えられるようタブが設置されていました。
タブの切り替え自体は難しいことではないですが、視聴していない方のタブに現在配信中のセッションタイトルが表示されるという仕様をどう実装するかで迷いました。

最初は JS で Json を読み込み時間になったら切り替えるというのも考えたのですが、JS の場合ユーザーの環境によって時間がずれる可能性があるため、時刻が関わるデータの取得は全てサーバー側で実行することにしました。
そのため、JS では1分ごとにサーバー(Json)にデータを取りに行き、返ってきたデータを出力するという処理のみ実施しています。

時間でコンテンツが変わる

イベント(最初の配信)が始まる前、配信中、配信終了後で「開始までお待ちください」「終了しました」などコンテンツを変える必要がありました。結果的には配信ツールの方で動画内に表示ができたので不要だったのですが、配信動画自体がぎりぎりまで来ず仕様が不明だったため、現在のステータスを取得・ステータスごとにコンテンツを切り替えるという処理が入っています。

  • DAY1 配信前
  • DAY1 配信中
  • DAY1 配信終了~DAY2 配信前
  • DAY2 配信中
  • DAY2 配信後

リアルタイムに現在配信中のセッション情報を表示

上記の「2トラックを並行配信」の通り、JS で1分ごとにデータを取りに行く処理の中に含まれています。
取得元を DB から Json に変えたことで処理はだいぶ軽くなってはいましたが、数百人のユーザーが1分ごとにデータを取りに行くのは負荷的に大丈夫なのか?という不安があったため、できる限りデータを取りに行く処理はまとめ、返ってきたデータを元に JS で表示を変えるような実装となっています。

負荷については、事前に負荷テストを行う予定ではあったのですが実装が間に合わずぶっつけ本番となりましたが、結果的には問題ありませんでした

セッション中にアンケートを表示する

今回一番ネックだったのがこちらの処理です。各セッションの終了7分前から終了時刻までアンケートへの回答を促すバナーを表示という仕様でした。

バナーは押下するとアンケートフォームが開き、「×」ボタンを押下すると縮小するという仕様です。縮小した状態を押下すると再度バナーが開きます。
時間通りにバナーを表示する処理自体は上記の1分ごとにデータを取りに行く処理に含められたのですが、逆に1分経つと状態がリセットされるということになってしまいました。

仕様を相談させて頂き、最終的には状態を Cookie に保存、最初に表示するときはバナー状態、2回目以降は縮小した状態で表示することになりました。

  • アンケート表示前(セッション終了の7分以上前)
  • 1回目の表示(バナー状態)
  • 2回目以降の表示(縮小した状態)
  • アンケート回答済(アンケート送信処理の中で Cookie を更新しています)

この場合バナーを拡大したタイミングでたまたま1分ごとのアップデートが走ると一瞬で縮小されてしまうのですが、工数を鑑みて今回はそれで OK となりました。
先述の通り Ajax による非同期通信がどのくらいの負荷になるのか読めず、できるだけ通信はしないよう (※) に作っていたのですが、結果あまり負荷はかからないと分かったのでバナーを開閉したら状態を Cookie に保存する処理を入れても良かったかな と思っています。
※JS で Cookie を保存すると PHP で取得することができないので、バナーの開閉と同時に非同期通信し PHP で Cookie を保存する必要がありました。

終了したセッションはアーカイブ化

元々の依頼では各セッションが終了したら一覧に都度加わる という仕様だったのですが、その場合もセッションが終了したかデータを取りに行く=非同期通信が走るため、最初から全てのセッションを表示・トリガーを押下して初めて通信が走り、そこで取得するデータで終了済か分かるような仕様に変えて頂きました。

開催日やカテゴリーなどでセッションを絞り込むことができるのですが、この実装が一番時間がかかったかもしれません。全て押したら All が ON になってそうでなければ All は OFF になってそれが4種類あって同時に AND 検索で…… という複雑な仕様だったためトップページの「TIME TABLE」にある絞り込み処理をそのまま流用することができず、結局 Ajax を使って PHP 側で処理させる形になりました。

ログインページ・スタンプラリーページ

ログインとスタンプラリー機能はシステム側で API を実装、組み込んだページです。
今回システム側は最低限の工数・できる限りノーコードで実装するため、通常 DB を使用するところを Microsoft Lists に置き換えて実装していました。

今回システムが関わったのは、申込フローリマインドメールログインフローの3点です。

水色がシステム黄色がフロントエンド の実装が必要な部分です。

申込フロー

登録処理自体は RPA が実行してくれるので、フロントエンド側は入力項目を指定のメールアドレスにメールするだけという簡単実装でした。

  • ユーザーが集客ページの申込フォームから項目を入力する
  • フォームを送信すると指定のメールアドレスに入力項目が送信される
  • 届いたメールの内容から RPA が必要なデータを読み取り、Lists に保存
  • 同時にアカウント情報を埋め込んだQRコードを発行し、ユーザーにQRコードを添付したメールを送信

リマインドメール

イベント開催が近付くと、登録ユーザーにリマインドメールを送信するという処理です。
こちらについてはフロントエンド側は作業無しでした。RPA を介して Lists から参加者データを抽出し、任意の日時にQRコードを添付したメールを一斉送信するという機能でした。

ログインフロー

今回オフライン開催(会場参加)とオンライン開催(ブラウザで視聴)を同時開催するため、オフラインではメールに添付したQRコードを端末で読み取って判別オンラインではログインフォームから入力して判別という2つのフローがあります。

  • オフライン(会場参加)
  • ユーザーがメールに添付されたQRコードを表示、運営が端末で読み取る
  • QRコードに埋め込まれたアカウント情報を Lists と照合し、入館可能か判別する
  • 結果を端末に返し表示する
  • オンライン(ブラウザで視聴)
  • ユーザーがログインフォームからメールアドレスを入力
  • メールアドレスをAPIに送信Lists と照合し、有効なメールアドレスか判別する
  • 返ってきた結果によってログイン、またはエラー処理を実行する

課題

概ね順調に進んだ一方、いくつか課題は残りました。

スケジュール管理

配信ツールの決定・検証用コードの発行・システム側の実装など各作業に細かく期限を設定していたのですが、全てが揃ったのはライブアップ前日とぎりぎりのスケジュールでした。

ミーティングごとに議事録は残していたものの見返す機会が少なく、またまとめて見ることができないため、あらかじめガントチャートのような形で用意しておくべきだったと途中で気付きました。
予期せぬ遅れが発生することを前提に、全員が他のメンバーの進捗を俯瞰できる場を作っておくべきでした。

アンケートが表示されない

配信中、各セッションの終了7分前から終了時刻までアンケートが表示されるのですが、リアルタイムのチャット欄では「アンケートが表示されない」というコメントを多々見かけました。
その場で検証を実施し、運営メンバー以外も巻き込んであらゆるデバイス・ブラウザで配信ページを見守っていましたが、結局その場では全ての環境で想定通りアンケートが表示されたため(もし実際にアンケートが表示されない環境があったとすれば)原因不明となってしまいました。

技術的な原因が見付からなかった一方、人為的な原因があったのでは?という仮説が挙がりました。それはセッション終了時にアンケート回答を促すアナウンスでした。
前述の通り、アンケートの表示は終了7分前から終了時刻までという仕様でした。そのためセッションが伸びた場合、終了時にアナウンスがされる頃には既にアンケートが消えているということになります。
特に会場参加のユーザーはセッションが終わってからWebページを開くので、アンケートを一度も目にすることも無かったのではないかと考えられます。

事前準備の段階では「オフライン開催の方はオフライン担当、オンライン開催の方はオンライン担当」というところがあり、双方の仕様に噛み合わないところがあったというのがアンケート問題の大本の原因だったのではないかと考えています。実際のセッションの流れをフロントエンド側も把握しておくべきだったと思います。
また、配信ページ内に置くのではなく独立したアンケートページを用意しておくなど予期せぬ事故が起きても他が動くよう、機能を切り離すべきでした。

配信中に機能停止してしまった

今回一番の課題はリクエスト過多で機能停止してしまったことでした。短時間のアクセス集中に耐えられず、受付からスタンプラリーまで全てが停止してしまい配信中に改修作業を実施しました。

こちらについてはシステム側で精査しているようですが、フロントエンド側でもなるべく負荷をかけない実装を心掛けるべきでした。
例えばスタンプラリーページはアクセスの度に RPA にアクセス・ログイン判定を実施していたのですが、途中で結果を保存し RPA へのアクセスを減らす仕組みに変更しました。

まとめ

ひとまず終わって良かったと同時に、ああしておけば良かったという反省点も多くあります。
去年一番の課題だった「事前確認」が今年は解消された一方で、また新たな課題も発生しているため、来年に向けてブラッシュアップを重ねていきます。

ブログの著者欄

デベロッパーリレーションズチーム

GMOインターネットグループ株式会社

イベント活動やSNSを通じ、開発者向けにGMOインターネットグループの製品・サービス情報を発信中

採用情報

関連記事

KEYWORD

採用情報

SNS FOLLOW