Firebase

【アプリ開発者必須】面倒な処理はCloud Functionsに任せよう

ユーザーに見えない処理はすべてCloud Functionsに任せよう

みなさん、Cloud Functionsをうまく活用していますか?

この記事は、Firebaseでのアプリ開発においてViewに影響しない処理はCloud Functionsに投げてしまおうという話です。

例えば以下のような処理は、すべてCloud Functionに任せることができます。

  • Cloud Storageに保存したデータのメタデータ設定
  • Authenticationの設定
  • 定期的なデータ削除

ということでこんにちは、株式会社Playground Webシステム開発部の稲垣です!

Firebaseはバックエンドの大部分を肩代わりしてくれるサービスですよね。

そして、Cloud Functionsをうまく使うと、SwiftやJava(Kotlin)のコード量を減らして、クライアントの負担を軽くすることができます。

なぜCloud Functionsを使うのか?

本来、クライアントは画面や操作に影響する処理のみを扱うべきだと思います。

そうではない処理はサーバーに任せてしまった方が良きですよね。

(ユーザー数の多いアプリケーションの場合、サーバーへの負荷分散のためあえてクライアント側に処理を任せることもあると思いますが。)

Cloud Functionsはデータベースやストレージに変更があった際など、イベントをトリガーに実行できるので「後でこれやっておいて〜」という処理を実装するのに便利です。

弊社ではザックリ以下のように分類しています。

  • すぐにレスポンスが欲しい → Swiftで実装
  • 後から処理してくれれば良い → Cloud Functionsで実装

UI/UXの観点からどちらで実装するか選べば良いかなと思います。

Cloud Functionsを使う準備

※Firebaseを使ったことがある方向けに端折って書いています。

  1. firebase initする際にFunctionsを選択、JavaScriptかTypeScriptを選ぶ
  2. firebase init完了後に作成された`functions`フォルダ内で`npm install -S firebase-functions firebase-admin`

functions/src/index.ts

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
admin.initializeApp(); // 最近、optionsを指定する必要がなくなりましたね

Cloud Functionsでよく実装する機能たち

Playgroundで開発する中で実装してきたCloud Functionsたちをいくつか例としてあげていきます。

特定ユーザーにAdmin権限の付与

functions/src/index.ts

exports.addAdminClaim = functions.database.ref('admin/{adminId}')
    .onCreate((snap: any, context: any) => {
        const uid = context.params.adminId;
        modifyAdmin(uid, true);
    });

const modifyAdmin = (uid: string, isAdmin: boolean) => {
    admin.auth().setCustomUserClaims(uid, {admin: isAdmin}).then(() => {
        console.log(`Successfully changed [${uid}]'s authentication.`)
    }).catch((error) => {
        console.error(`Failed to change [${uid}]'s authentication. `, error)
    })
};

Firebase Authで作成したユーザーのUIDを、adminモデルに追加した時(onCreate)、カスタム権限を設定して管理者扱いにできます。

動画アップロード時にサムネイルを自動生成

動画を扱うアプリケーションであれば、サムネイルを設定したいという要件はきっとありますよね。

これもCloud Functionsにお任せすることができます。

コードを載せるととても長くなるので、参考にした記事リンクを貼っておきます。

Firebase Storage に動画ファイルがアップロードされたら Cloud Functions で自動的にサムネイルを作成する

画像アップロード時にキャッシュを設定

functions/src/index.ts

exports.setMetadata = functions.storage.object().onFinalize((object: any) => {
    const filePath = object.name;
    const { contentType } = object;
    const fileRef = bucket.file(filePath);
    const newMetadata = {
        cacheControl: 'public,max-age=86400',
    };

    // ここでcontentTypeに応じてメタデータを変えてみたりとか
    if (contentType.startsWith('image/')) {
        fileRef.setMetadata(newMetadata).then(() => {
            console.log('Set Metadata'); // eslint-disable-line
            return true;
        }).catch((err) => {
            console.log(err); // eslint-disable-line
            return false;
        });
    }
});

画像ファイルにキャッシュを設定して次回の表示を高速化できます。

Cloud Storageのデフォルトは3600秒ですが、サンプルコードでは86400秒=24時間に設定してみました。
(要件に応じてチューニングしてください)

データ削除時にひもづく画像/動画/ファイルをCloud Storageから削除

functions/src/index.ts

exports.fileDelete = functions.database.ref('hoge/${id}')
    .onDelete((snap: any, context: any) => {
    // idと削除対象のファイル名を同一にしている場合
    const id = context.params.id;
    // fugaフォルダのidと同じ名前のjpegファイルを削除
    return admin.storage().bucket().file(`/fuga/${id}.jpeg`).delete();
});

detabaseのデータ削除をトリガーに、データIDと同じファイルをCloud Storageから削除します。

クライアント側ではDBのデータ削除処理だけを書けばOKです。

Cloud Functionsのまとめ

Cloud Functionsの使い所
  • 「データを削除した時に一緒にこれも消したい」
  • 「何かを作った時に、設定値を追加しておきたい」

上記のような処理をさせるには便利だな〜という印象です。

デバイスにPush通知を送るときにCloud Functionsは必須なので、iOS/Androidエンジニアの人もある程度かけるようになるとハッピーですね。

ABOUT ME
稲垣 貴映
サーバーエンジニア兼Webフロントエンジニア。 新卒で独立系SIerに入社後、金融系システム基盤の構築・運用を3年間経験。 プログラミングを独学していた頃に、CEOの馬谷が開講していたSwiftスクールに通い、2019年9月に入社。 趣味はブラジル音楽の演奏。

COMMENT

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA