stand.fmでのFirebase活用事例 ~React Native x Firebaseのメリット~
(このnoteはstand.fm engineeringマガジンの記事です)
stand.fm エンジニアの和田です。
今回は先日、先日開催されたイベント PORT Firebase × React Native の振り返りと、またイベント内では語り尽くせなかったstand.fmでのFirebase活用方法をご紹介したいと思います。
Firebase x React Native 登壇レポ
このイベントではStamp社とstand.fmの共同開催で行われ、stand.fmからは私、和田と、三堀さんが登壇しました。
(YouTubeアーカイブはこちら:https://youtu.be/twuljHeMFCI )
React Native x FirebaseのメリットとTips 5選
和田からは「React Native x FirebaseのメリットとTips 5選」というテーマで発表させていただきました。 stand.fmにジョインする以前から、複数のアプリをReact Native x Firebaseで開発してきましたが、この組み合わせの開発効率はとてもよいと感じています。
まずバックエンドのFunctionを含め全てJavaScript(TypeScript)で書けること。 またReactの思想にある「Learn once, write anywhere」の通り、アプリだけでなくweb管理画面やwebアプリもReactの知識で一気通貫に開発できるのが効率が良いです。
また個人的に便利だと思うTipsを5つ紹介させていただきました。 詳細はスライドをご参照下さい。
stand.fm(Android)におけるreact-native-track-playerの改善
三堀さんからは「 stand.fm(Android)におけるreact-native-track-playerの改善」をテーマに発表いただきました。 stand.fmのアプリはReact Nativeで開発されていますが、音声の録音/再生やライブ配信など、React Nativeだけで実装が難しいところは、積極的にnative moduleを使って開発しています。
音声の再生のためにreact-native-track-playerというライブラリを使用しています。 しかしUX改善のために足りない機能もあり、そこについてはforkして独自実装をしています。 三堀さんは元々Androidネイティブの開発の経験が豊富なため、このあたりのAndroid Native moduleの開発で活躍されています。
このように弊社ではiOSやAndroidのネイティブ開発に強いエンジニアの活躍できるシーンも多くあります。
stand.fmのFirebase活用
イベントの際は詳しく語れなかなったのですが、stand.fmでもFirebaseを利用しています。
主に以下のような機能を使っています。
・ Firebase Authentication
・ Firebase Remote Config
・ Firebase Crashlytics
・ Google Analytics for Firebase
・ Firebase Cloud Messaging
Firebaseを使う場合、DBにFireStore、バックンド処理にCloud Functionsを利用して、バックエンドを完全にFirebaseのみで構成することも可能ですが、弊社の場合はFirebaseの必要な機能を部分的に使う形になっています。
このあたり判断は、開発するサービス次第になってきますが、以下のようなケースでFirebaseのみの構成は不向きだと感じています。
🤔 マスターテーブルのjoinが多く発生する場合
FireStoreはNoSQLでjoinがないため、たくさんのマスターを結合して使うようなシステムでは向いていません。 この場合はRDBの方が向いています。 例えば業務システムなどでこの傾向は強そうです。
🤔 バックエンド側の実装が多くある場合
Cloud Functionsでバックエンドを書くことも可能ですが、Cloud Functionsは起動に時間がかかる、deployに時間がかかるなどの使いにくさもあります。 自前でバックエンドを構築するほうがよさそうです。
さて、話を戻してstand.fmでのFirebase利用についてもう少し詳しく見てみたいと思います。
今回はAuthenticationとRemote Configを取り上げます。
Firebase Authenticationの利用
stand.fmではバックエンドはNode.js、データベースはmongoDBで開発しています。
ここでユーザー認証の部分だけFirebase Authenticationを使っています。 ユーザー認証はどんなサービスでも必要となる機能ですが、この部分だけFirebaseを使うことで工数を削減できます。SNSでのログインやパスワードを忘れたときの再設定など..地味に大変だったりしますよね。
特に匿名ログイン機能は便利だなと感じます。
stand.fmではアプリを初めて起動すると、まずは匿名ユーザーとしてログインします。 ユーザーによっては配信を聴くためだけにアプリを利用する場合もあります。その場合すぐにアプリを使い始められるのはよい体験だと思います。
以下に、Firebase Authenticationと自前のAPIサーバーを組み合わせて使う流れの一例を図にしました。IDトークンという仕組みを使って認証を行います。
参考(公式ドキュメント): https://firebase.google.com/docs/auth/admin/verify-id-tokens?hl=ja
アプリ側
まず firebase.auth().signInAnonymously() で匿名ログインします。
続いて自前のAPIサーバーのAPIを叩くのですが、この際、ユーザー認証するためにまずはFirebaseのIDトークンなるものを取得します。
そしてそのIDトークンをAuthorizationヘッダーに付加してAPIを呼び出します。
const token = firebase.auth().currentUser.getIdToken()
const result = await fetch(
'https://my-server/api/messages',
{
headers: {
Authorization: `Bearer ${token}`,
}
}
)
サーバー側
Authorizationヘッダーにて渡されたIDトークンを使って、Firebase Authenticationのuidを取得します。
その後そのuidを使って、自社のDBから何らかのデータを取得するなどします。
const authenticate = async (req, res, next) => {
// Authorization HTTP headerにて渡されたidTokenを検証
const idToken = req.headers.authorization.split('Bearer ')[1];
try {
const decodedIdToken = await admin.auth().verifyIdToken(idToken);
req.user = decodedIdToken;
return;
} catch(e) {
res.status(403).send('Unauthorized');
return;
}
};
app.get('/api/messages', async (req, res) => {
// Firebase Authenticationのuid
const uid = req.user.uid;
// uidをキーに自社DBからデータ取得するなど...
}
参考: https://github.com/firebase/functions-samples/blob/master/authenticated-json-api/functions/index.js
Remote Configの利用
続いてRemote Configについても触れてみたいと思います。
以下、公式ドキュメントによるとRemote Configの説明です。
Firebase Remote Config は、ユーザーにアプリのアップデートをダウンロードしてもらわなくても、アプリの動作や外観を変更できるクラウド サービスです。
ユースケースとしては例えば、
・一時的なキャンペーンの表示切り替え
・メンテナンスモードの切り替え
など各ユーザー毎の切り替えというよりは、全ユーザーに対して何らかの表示を切り替えるときに使うことが多いようです。 値をランダムにする機能もありABテスト用途にも使えるそうです。
stand.fmでは例えば、アプリの最低動作バージョンをRemote Configに保存しておくことで強制アップデート機能を実装しています。
Remote Configを使えば、以下のようなwebの設定画面も用意されていて、非エンジニアにそれらのフラグ管理も任せることができるので、ちょっとしたアプリ内の設定はRemote Configを使うと便利です。
アプリ側でのRemote Configの値の取得は、React Nativeの場合、以下のような形になります。簡単ですね!
import remoteConfig from '@react-native-firebase/remote-config
(中略)
await remoteConfig().setConfigSettings({})
await remoteConfig().fetchAndActivate()
const versionMin = await remoteConfig()
.getValue('app_ver_min')
.asString()
まとめ
以上、先日開催されたイベント「PORT Firebase × React Native」のレポートと、またイベントの際には語りきれなかったstand.fmでのFirebase活用についてご紹介しました。
今回ご紹介したように、Firebaseの機能は必要なものだけを選んで導入することも可能なので、既存のプロジェクトにも必要に応じて導入できると思います。
なにかの参考になれば幸いです。
・・・
stand.fmではエンジニアを積極的に募集しています。
定期的に技術イベント開催してるのでぜひチェックしてみてください。