リモート忘年会を盛り上げるためのクイズサービスを3日で作るためにやったこと

はじめまして、株式会社マクアケでエンジニアをしている@tokutoku3です。

この記事は [Makuake Advent Calendar 2020](https://adventar.org/calendars/5986) 15日目の記事です。（大遅刻)

# はじめに

タイトルの通り、弊社では今年の忘年会を**完全リモート**環境で実施することになっています。

その中で、どうせならこの環境で楽しめることをやりたいという話になり、
全員参加型のクイズサービスがあれば盛り上がるのでは...という流れからとりあえず作ってみることになりました。

なりました、というか個人的にFirestoreを使ってこんな感じのサービスをつくるお勉強をしたいなと思っていたので、~~鴨がネギ~~ 渡りに船という感じでウキウキしながら開発にとりかかりました。

# 1. ざっくりとした要件整理

元々忘年会でサービスを開発するなんて発想は(当初)企画陣にはなかったので、
具体的にこういう要件で...という話はありませんでした。

０からあれこれ仕様を考えるのは大変なので、
今回は年末恒例の某感謝祭をリスペクトした早押し４択クイズができるようにします。

ある程度企画陣で共通の認識を持ちつつ、細かい仕様決めに割く時間を削減できるので、
社内コンテンツを考える場合はまずリスペクト先を選ぶのが大事だなと思いました。


# 1. ライブラリやサービスの選定

やる気満々で始まったクイズサービス実装ですが、
普段のお仕事もありますし、なにより忘年会までの時間は限られています。

Firestoreを今回新規に触ることになるので、
それ以外の要素は**基本的に経験のある、調査の必要がないものを選定する方針**にしました。
![スクリーンショット 2020-12-28 16.36.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199813/2617c889-48a4-fd32-ebff-6dbcb5a4cb90.png)


## Vue.js v2
Nuxt.jsではなくVue.jsを採用したのは、今回作成するページが以下の３つのみで少なかったためです。

* クイズ画面
* クイズ回答画面
* 操作用の管理画面

特にNuxt.js由来で使いたい機能もなかったので、ビルドファイルサイズ削減のために最低限の構成としました。

また、今回サービスを作るにあたって**デザイナーが不在**(一人だけで開発していた)だったため、
下地にはUIライブラリをつかい、必要なところだけcssを書けばいい状態を目指しました。

Vue関連のUIライブラリはそのほとんどが絶賛Vue3対応中だったため、
今回はVue2系の最新を採用しています。

## Firebsase Authentication

今回の企画では事前にチーム分けや、回答後に集計してランキングを付けたいなどの話が元々あったため、
各参加者を識別できる必要がありました。

Firebase Authenticationであれば希望のプロバイダを使った認証が簡単に用意できるので、
今回はセットで利用しています。

## S3

ビルドしたファイルの配信用ストレージとして、今回はS3を採用しました。
CloudFrontやWAFを組み合わせたカスタムドメインの割り当て/アクセス制御ができる環境構築用のTerraformを作っていたのでそれを使いまわしたのですが、FirebaseのStorageやHostingを使うでも全然問題なかったとは思います。

## Firebase firestore

今回サービスを作る上での挑戦ポイントです。
まず導入にあたって[公式ドキュメント](https://firebase.google.com/docs/firestore?hl=ja)に一通り目を通しました。

ドキュメントやコレクションなどの話は、他のNoSQLを触ったことがあればとっつきやすい概念だと思います。
[firestoreにおけるベストプラクティス](https://firebase.google.com/docs/firestore/best-practices?hl=ja)もドキュメントにまとまっていたので、基本的に踏襲する形で実装を考えていきます。



# 2. データをどう持つか検討

構造検討にあたって、下記の記事は大変参考になりました。
> Cloud Firestoreを実践投入するにあたって考えたこと
> https://qiita.com/1amageek/items/d606dcee9fbcf21eeec6

今回は小規模なデータ構造でよかったため気に掛けるポイントは多くなかったですが、
それでもベースにこの考え方があったかどうかで進め方は大分違っていたと思います。

とはいえ、実装にとりかかるタイミングでは詳細な仕様は決まっていないので、
今回は下記のデータを持つことを最初に決め、細かいフィールドについては作りながら考えてくスタイルにしました。

* クイズ一覧
* 今出題しているクイズ
* クイズの回答
* ユーザのチーム分けや表示名に関する情報


# 3. とりあえずプロトタイプをつくる

ここに大体２日分の時間を使いました。


## 管理

今回作業時の検討や実装タスクの管理には[Whimsical](https://whimsical.com/)というサービスを使用しました。
`The Visual Workspace` というフレーズにある通り、図やテキストを始め提供される色々な機能を使いながら作業を管理することができます。

１つのworkspaceで下図のように作業用の情報をまとめていたのですが、
存外使いやすかったので、小規模な個人開発ならこれで事足りる印象を受けました。

![スクリーンショット 2020-12-28 11.01.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199813/09002db1-a001-41af-c4ab-e0537724b83e.png)

## とにかく実装

デザインはさておき、今回やりたいことのベースをガンガンつくっていきます。
大きく4つのステップに分割し、プロトタイプを作っていきました。

1. Firestoreのデータを読み込んで出題、カウントダウン、正解表示ができるクイズ画面の実装
2. Firestoreのデータを操作できる管理画面の実装
3. Firestoreのデータに応じて回答可/不可の制御ができる回答画面の実装
4. Terraformを使って配信用のS3+α環境を構築、アップロードして動作確認

こういう(仕様が決まりきっていない)プロトタイプを作る上で順番を決めておくのは大事なポイントだと思っていて、
例えば管理画面から作り始めてしまうと「実際何を管理したいのか」が不明瞭なまま進むことになり、
実装の手戻りや大きな構成変更が後から発生してしまう可能性が高まります。

**これ(プロトタイプの仕様)が決まってればあとは実装するだけ**、という状態を作りやすい段取りを常日頃考えたいものです。

# 4. 企画陣とやりたいことのすりあわせ

本格的な企画検討が始まる前にプロトタイプを用意できたので、
プロトタイプベースでやりたいことや当日の進行を相談できました。

実装の観点では、

* 画像を用意してもらうところ
* 演出を派手にした方がいいところ
* 結果を集計する際に指標とする項目

などの相談をこのタイミングでおこない、スケジュール的に可能な範囲でTODOリストの洗い出しを行いました。


# 5. 微調整

相談した結果を元に集計系の画面を作ったり、演出の調整をしたのがこのフェーズになります。
ここまで来ると丸１日この作業にとりかかっていたタイミングはなく、ちょっとした隙間時間に準備を進めるような流れになっていました。

その中でデータ項目の追加なども細々発生したのですが、FirestoreはNoSQLなので、
ちょっとしたスキーマの変更があってもすぐに対応できたのがとても扱いやすかったです。

また、この辺りでFirestoreの読み取り/書き取り/削除の使用量が大体把握できてきたので、
忘年会当日に参加する予定人数で掛け算をして、Spark(無料)プランで収まるかどうかの試算などもこのタイミングでおこないました。

> Cloud Firestore の課金について
> https://firebase.google.com/docs/firestore/pricing?hl=ja

# 6. リハーサル

今回はFirebase Authenticationを利用してあらかじめメールアドレス認証用のアカウントを作成しています。
リハーサル前日にログインの動作確認依頼を全体に共有し、リハーサル当日はクイズ回答部分の確認に集中できる流れにしました。

結果として、当日参加する人数の2/3程度に対してサービスのリハーサルができ、
無事問題なく動くことを確認できました🎉 (一安心)

Firestoreの使用量に関して、事前に試算した内容から大きく外れていないこともこのタイミングで確認できたのがよかったです。
ただ、FirebaseのSparkプランは使用上限を超えると各サービスを利用できなくなってしまうので、
念を入れてBlazeプランに切り替えを行いました。
(Blazeプランの無料枠で収まる想定なので、あくまで保険として)

あとは忘年会本番を待つのみ！

# 終わりに

「３日で」というのは若干盛っていて、期間で言えば１週間くらいあったのですが、
実際に手を動かした時間で言うと大体３営業日分くらいだったかと思います。

今回突貫でクイズサービスを作ってみて、
時間をかけずに、とりあえず動くものを作りたい場合にFirebaseはかなりパワフルなサービスだなと改めて感心しました。

忘年会後に新しい情報があればまた追記します。
それではみなさま、良いお年を！