Firebaseのサーバレス運用に移行して良かったこと

# 概要

「[秘密のアンケ](https://h-anke.net/)」というサービスをリリースしました。

https://h-anke.net/

今までのサービスではCentOS＋Nginx＋PHP＋MySQLという構成を使用していましたが、今回はFirebase＋Node.jsというサーバーレス構成に移行しました。
その前後を比較して、良かった点とそうでなかった点をまとめます。

※このサービスを作ろうと思った経緯や企画的なこだわりポイントは、[Zennの記事](https://zenn.dev/sanjimonica/articles/a535b304cd95b7)にまとめています。
　併せてご覧いただけると嬉しいです。

https://zenn.dev/sanjimonica/articles/a535b304cd95b7

# 環境
##### 移行前
* CentOS + Nginx + PHP + MySQL

##### 移行後
* Firebase（Hosting / Functions / RealtimeDatabase / Authentication）
* Node.js + Express

# 良かったこと

## Firebase

### サーバーレス運用ができる
最大のメリットです。サーバー落ちやスケーラビリティを気にしなくてよくなります。
ストレスから開放されて本当に良かったです。

### Firebase SDK が充実している
Node.js向けのSDKや公式ドキュメント、個人の記事などが充実しており、初めての使用でも特に迷うこと無く実装ができました。
SDKを使用せずに自前でFirebase用の実装をするということはありませんでした。
Firebaseの各サービス同士での連携も簡単なので、Firebaseに統一するメリットは大きいと思っています。

### NoSQLが使いやすい
RealtimeDatabaseにしたことで、半ば強制的にNoSQLを使用することになりました。
初めはRDBとの使い分けが理解できずに苦労しましたが、慣れると使いやすいです。
（私の理解では、RDBとの大きな違いは「テーブル定義が不要」「データの重複を許容して実装するべき」という点だと思っています。）

### その他細かいメリット
* RealtimeDatabaseに用意されている機能を使って、DBのバックアップが自動で作成できます。30日間バックアップも選べるため、無駄にFirebase上のストレージを消費することもありません。
* ローカルでFirebaseエミューレータが使用できるので、サーバーを立てて開発確認ができます。ただし、本番環境と挙動が異なる点があるので注意が必要です。（後述）
* 本番環境へのデプロイもコマンド一発で可能。ただし毎回数分かかります。
* SSL証明書が自動で発行され、設定や更新も不要。自分が所持しているドメインやそのサブドメインも利用できます。

## Node.js
Firebase FunctionsがPHPに対応していなかったため仕方なくNode.jsに移行しましたが、たくさんのメリットがありました。

### ライブラリが豊富
数多くのライブラリが存在するため、探せば大抵のものは用意されていました。npm を使用すれば導入も簡単でした。

### フロント側と言語を統一できる
フロント側でもJavaScriptを使用しています。そのため、同じ処理をフロント側とサーバー側で実装したいときは、コードをそのまま流用できました。
※一例を上げると、「ユーザー入力値に絵文字が入っていたら削除する」という処理をフロント・サーバーで実装しています。

### ネット上での情報が多い
PHPもメジャーなのでそんなに困ることは無いかもしれませんが、Node.js（JavaScript）についての情報はネット上に数多くあるため、見つけたい情報をすぐに入手できることが多いです。

# 移行で苦労した点（慣れていないがゆえのデメリット）

## Firebase

### 従量制の費用がかかる
今までは独自ドメイン以外は無料で運用できていましたが、Firebaseを使用するに当たり他にも費用が発生するようになりました。
特に割高というわけではなく現在の私の規模だとせいぜい月に数十円ですが、請求書が届くと少しドキドキします。

### エミュレータに癖がある
上で少し触れましたが、本番環境と挙動が異なる点があるので注意が必要です。
具体的には、HTTPのリクエストヘッダーの内容が異なります。
リファラー、アクセス元IPアドレス、Sec-Fetch-Site などが、エミューレータでは取得できませんでした。
開発環境用の処理を別途書いたり、処理をさせないように分岐させる必要がありました。

## Node.js

### PHPと同じ感覚で使えない
当然ですが、言語が変わると動作が異なる点がたくさんあり、慣れるまでが大変でした。
特に、リクエスト単位での変数スコープを使うことに苦労しました。
開発の終盤まで認識を誤っていたため、アプリケーション単位での変数スコープにユーザーのログイン情報を保存してしまい、大きなセキュリティー事故に繋がるところでした。（[Express向けの良いライブラリ](https://www.npmjs.com/package/express-http-context)があったため助かりました。）
本番環境での動作を想定して複数端末で同時に試験をするなど、いつも以上に試験に気を配る必要がありました。

# 良くなかった点

## Firebase

### Twitterログイン時の画面がカスタマイズできない
Authentication を使用してTwitterログインを実装していますが、PHPで他のライブラリを使った場合に比べてあまり好みでない動作にならざるを得ませんでした。
具体的には、下記のような点です。

* ログイン時に2回リダイレクトが発生する。
* ログイン時に薄紫色の画面が表示される。カスタマイズは不可。

これが気にならないのならあまり大きな問題ではないと思います。
私としても、Authenticationを使用するメリットが大きいため採用しました。

## Node.js

### Visual Studio CodeがEJSに完全対応していない
とても軽微な内容ですが、不満ではあったので挙げておきます。
VSCodeがExpress用テンプレートエンジンであるEJSに完全対応していません。
シンタックスハイライトはプラグインを入れることで解決しましたが、フォーマット時にインデントが上手く働きませんでした。
一応[こちらの方法](https://qiita.com/SanjiMonica/items/0b1034719f33529ace73)を使えば正しくインデントされますが、出力されたHTMLコードに余計なコメントが大量に入るので、結局採用はしませんでした。
また、他のテンプレートエンジンは、非エンジニア（デザイナー）には分かりにくいものと判断したため採用しませんでした。

# まとめ
慣れずに苦労することもあり、サービスリリースまでには少し時間がかかってしまいましたが、結果としてはサーバーレス構成に移行できて本当に良かったと思っています。
Firebaseの様々な機能を使用すれば今後別の要件にも柔軟に対応できると思うため、次回以降の開発もこの構成を使用する予定です。

プログラム仲間を募集中です！どうぞお気軽にご連絡いただけると嬉しいです！
◆Twitter（[@SanjiMonica](https://twitter.com/SanjiMonica)）

# 関連記事
[サーバーレスで動的サイト作成（Firebase Hosting + Cloud Functions + Node.js + Express + EJS）](https://qiita.com/SanjiMonica/items/fdbe3290a8f571cdaecc)

# 最後に
ツイートを記事に埋め込めば、Qiita上でもアンケートができることに気がつきました。なかなか便利かも・・・。
もしよろしければご回答お願い致します！

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">今回のQiitaの記事、どうだった？<br>A：大変参考になった！<a href="https://t.co/RA6x4edxKt">https://t.co/RA6x4edxKt</a><br>B：まあまあ参考になった<a href="https://t.co/QaC1l1Ls31">https://t.co/QaC1l1Ls31</a><br>C：あまり参考にならなかった<a href="https://t.co/lOWhGmWsQs">https://t.co/lOWhGmWsQs</a><br>D：ぜんぜん参考にならなかった<a href="https://t.co/1JD4QkK0hB">https://t.co/1JD4QkK0hB</a><a href="https://t.co/gwu87Y9KMS">https://t.co/gwu87Y9KMS</a><br> <a href="https://twitter.com/hashtag/%E7%A7%98%E5%AF%86%E3%81%AE%E3%82%A2%E3%83%B3%E3%82%B1?src=hash&amp;ref_src=twsrc%5Etfw">#秘密のアンケ</a></p>&mdash; サンジモニカ｜個人開発やってます (@SanjiMonica) <a href="https://twitter.com/SanjiMonica/status/1434454157985861638?ref_src=twsrc%5Etfw">September 5, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>