SMARTCAMP Engineer Blog

スマートキャンプ株式会社(SMARTCAMP Co., Ltd.)のエンジニアブログです。業務で取り入れた新しい技術や試行錯誤を知見として共有していきます。

リアルタイムにRDBを扱えるBaaS「Supabase」を使ってみた

こんにちは!!!スマートキャンプでエンジニアをしている吉永です!

私は現在、スマートキャンプの主力サービスであるBOXILの開発にフロントエンド、バックエンド問わず携わっています。

初めに

皆さんはFirebaseというBaaS(Backend as a Service)を利用したことがありますか?

Googleが提供元のモバイルやWebアプリケーション向けのサービスで、RealtimeDatabase(NoSQLなリアルタイムDB)やFirebaseAuthentication(さまざまな認証機能)が搭載されている便利なサービスです。

私は現在SNS認証などを実装する場合、FirebaseやAuth0のようなBaaSを利用していますが、データベースに関してはRealtime Databaseなどは利用せず、PostgreSQLなどのRDBを構築して使っていました。

「嗚呼、RDBなFirebaseが欲しいなぁ」とたまに感じながら生きてたら、それをそのまま体現したかのようなSupabaseというサービスがあることを知り、興味を持った次第です。

今回の記事では、そんなFirebase Alternative(Firebaseの代替)と言われるSupabaseについてご紹介したいと思います。

Supabase公式サイト

Supabaseとは

Supabaseのドキュメントを読むと、「Supabase is an open source Firebase alternative.」と書かれています。

オープンソースになっているFirebaseの代替と謳っているこのBaaSは、現在以下の機能を提供しています。まずは簡単に各種機能の説明をしたいと思います。

PostgreSQLベースのデータベース

Firebaseで実装されていたRealtimeDatabaseはその名の通り、データの更新に合わせてリアルタイムに変更を検知できることが最大の特徴となっています。

しかし、NoSQLではデータの整合性を保証しないため、削除や更新処理が頻繁に発生した際に整合性を保ちづらい点や、SQLを使用できないため複雑な検索をしづらい点などの課題感もあり、便利は承知の上で実用には足踏みしてしまう方も多いのではないでしょうか。

反対にSupabaseで導入されているのはPostgreSQLで、ここがFirebaseとの大きな違いになってくるかと思います。まさにFirebaseのRDB版と言った具合でしょうか。

テーブルやカラムの管理なども、Firebase同様管理ページから管理できます。

公式ドキュメント

認証

先ほども書いたとおり、私は現在SNS認証などを手軽に開発したい場合は、認証のみFirebaseかAuth0に頼る形で使っていました。

上がSupabaseでSNS認証対応しているサービスで、Firebaseと同じように多様なサービスがサポートされています。

公式ドキュメント

ファイルストレージ

お馴染みのファイルストレージ機能です。

ここは特に代わり映えがあまりないので特に説明はしません。

公式の説明を読んでいると動画やメディアのファイルプレビュー機能がしっかりしてそうで、今度色々なファイルを上げて試してみたいです。

公式ドキュメント

APIの自動生成

管理画面からテーブルやカラムを追加した際に、自動的にAPIへのルーティングを生やしてくれる機能です。

公式ドキュメントにも例としてありますが、ToDoテーブルを作った際、ToDoに対するGET、POST、PATCH、DELETEのリクエストを走らせることができるようになります。

下にドキュメントに記載されている例文を載せておきます。

// Initialize the JS client
import { createClient } from '@supabase/supabase-js'
const supabase = createClient([SUPABASE_URL], [SUPABASE_ANON_KEY])

// Make a request
let { data: todos, error } = await supabase
  .from('todos')
  .select('*')

また、FirebaseのRealtimeDatabaseと同様、リアルタイムでのデータ変更の検知を可能としていると書かれているため、この後実際に作ったりしながら実験してみようと思います。

公式ドキュメント

料金プラン

現在、Supabaseの料金プランは以下のようになっています。

Supabaseの料金プラン

テストや趣味用のフリープランは無料で使えますが、その他は25$からになっているようです。

リアルタイムデータベースのサポートや、APIリクエストなどはフリープランでも無制限になっています。

認証に関しても、無料プランでは10000ユーザーになっており、個人で使う分には十分です。

認証方法に関しても、無料プランと有料プランで違いはないです。

他サービスとの料金比較

ここでFirebaseやAuth0の無料プランとの比較をしてみたいと思います。

データベースに対する操作数

Supabase Firebase
書き込み 無制限に無料 1日2万回
読み込み 無制限に無料 1日5万回
削除 無制限に無料 1日2万回

データベースの性能

Supabase Firebase
容量 500MB 1GB

このように、DBに対する操作に関してはSupabaseの方が優れていそうです。

しかし、無料で使えるDB容量に関してはFirebaseの方が大きいことがわかります。

認証

Supabase Firebase Auth0
アクティブユーザー 10000ユーザー 電話認証月1万 / その他無限 7000ユーザー

認証では、Firebaseが無料で使えるアクティブユーザーの登録数が多いことがわかりました。

試してみる

環境構築

早速試してみましょう。今回は公式ドキュメントにチュートリアルはありませんが、使い慣れているNuxt.jsでSupabaseを使用してみたいと思います。

まずはsupabaseのページで新しくプロジェクトを作ります。

regionは東京が用意されていたため、それを使っていきます。

次にNuxt.jsの雛形を作ります。

npx create-nuxt-app supabase-nuxt-example npm install nuxt-supabase

Nuxt.js用にはSupabaseのコミュニティで開発されているnuxt-supabaseがあるため、それを使いながら試していきます。

nuxt-supabase リポジトリ

終わったら、nuxt.config.jsに以下を追記します。

modules: [
  ['nuxt-supabase', {
    supabaseUrl: 'YOUR_SUPABASE_URL',
    supabaseKey: 'YOUR_SUPABASE_KEY'
  }]
],

YOUR_SUPABASE_URLとYOUR_SUPABASE_KEYは、Supabaseプロジェクトを作ったときに出てきたURLとApi Keyを入れてください。

また、プロジェクト作成時にTypeScriptを導入した方はtsconfig.jsonに以下の記述を追加してください。

{
  "compilerOptions": {
    "types": [
      "@nuxt/types",
      "nuxt-supabase"
    ]
  }
}

認証

あらかた整ったところで、認証を試してみようと思います。

設定画面から認証のページに飛び、認証を使用したいサービスを選びます。

Create new credentialsをクリックすると、そのサービスの認証用トークンを発行してくれるページに飛べるので便利です。

今回はGitHubのアカウントを使って認証してみたいと思います。

フォームに沿って必要な項目を入力します。

そして、発行されたIDやSecretをSupabaseに入力して保存したら設定完了です。

そしたら軽く認証用のコードを書いてみたいと思います。

this.$supabase.auth.onAuthStateChangeで認証状態の監視をします。

変更が行われた際に自動でcheckUserが走る感じですね。

実際にページにアクセスして、ログインボタンを押すと以下のようになります。

このままGitHubアカウントで認証すると、ログイン済みのステータスになりログアウトができるようになったことが確認できると思います。

このように、Firebase同様SNSログインなどの自分で実装するとめんどくさいものが、簡単にできるようになるのは一つの強みではないでしょうか。

データベースの作成、supabaseAPIの使い方

データベースの作成方法

次にデータベースを作っていきます。

今回は、会社とユーザーを紐付ける1 : Nになるテーブルを作っていきます。

Enable Row Level Securityにチェックを入れると、データへの本人以外からの書き込みに制限を設けるなどのセキュリティ対策ができます。

また、Nullableやリレーションなどもこの画面から設定できます。

まずはダッシュボードから会社を追加してみます。

必要な項目を入力して保存すると、このように新規のデータが追加されていることがわかると思います。

データの取得方法

そして、コード上では以下を追記します。

const { data } = await this.$supabase.from("companies").select("*")
if (data) {
    this.companies = data;
}

すると、このように先ほど追加したデータが取得できていることがわかります。

データの作成方法

次に、supabaseのAPIを使ってデータを追加してみます。以下をコードに追加してください。

await this.$supabase.from("users").insert({
    name: "test",
    company_id: 1,
}, { returning: 'minimal' });

実行すると、このように新しいユーザーが追加できていることがわかります。

リアルタイムデータベース

データの変更をリアルタイムで監視するには、デフォルトでオフになっているオプションをオンにする必要があります。

サイドバーからデータベースを選択し、Replicationからリアルタイムの検知を有効にしたいテーブルを選択してください。

そして、以下のように追記すると、.subscribe()で監視ができるようになります。

await this.$supabase.from("users").on("*", (payload) => {
  this.users = payload
}).subscribe();

また、on("INSERT")などとすると、INSERTやUPDATEのみでの発火設定も可能ですが、*を入れることによりすべての変更を監視できます。

が、現状セキュリティ的に不安な要因があるため、SupabaseはRealTime Databaseの使用をOFFにすることを推奨しています。

TypeScriptの型サポート

TypeScriptで使える型をデータベースから自動生成したい場合、openapi-TypeScriptで自動生成できます。

本記事では時間の都合上触れられていませんが、以下のドキュメントにまとめられています。

OpenAPIを使った型の自動生成

良かった点・不満点

良かった点

個人的に良かったところとしては、やはりRDBが使えたことだと感じています。

これまでリアルタイムに更新されるデータを扱いたいと感じた場合、簡単に実装する一番の選択肢はFirebaseでしたが、そのためにはNoSQLを使わなくてはならず、なかなか踏み出せずにいました。

SupabaseではPostgreSQLに対応しており、SQLやSpreadSheetからテーブルの作成やデータの移行に対応しているため既存のDBからの乗り換えもスムーズにできそうでした。

また、Row Level Securityのような書き込み、読み込みの権限をいくつかのテンプレートから設定できたのも便利ポイントだったように感じます。

もともとFirebaseを触っていたからというのもありますが、思ったよりもスムーズにリアルタイムなデータ同期ができた点も、満足度としては高かったです。

不満点

Supabaseに限った話ではないですが、クエリビルダで複雑なクエリを書くのが難しいです。

NoSQLの話をしたときの「SQLを使用できないという点から複雑な検索をしにくい」という点とは違い、フロントエンドで使えるクエリビルダの現状の限界という話である気がします。

セキュリティの都合上いくつかの種類のクエリはライブラリから叩くことができないため、難しいクエリを書く場合も合わせてPostgreSQLでおなじみviewを書き、それをフロントエンドで呼び出すことにより対処することになります。

SupabaseでViewを使う方法

しかし、クエリビルダを好んで使う温室育ちの僕にとって、生のSQLを書く行為は中々レベルが高いのでちょっと辛そう...という感じです。けれど、クエリビルダが使えないというだけでSQL自体は書けますしNoSQLで感じていたようなそもそもの検索のし辛さのようなものは感じにくいと思います。

まとめ

いかがでしたでしょうか。

本記事では、Firebase AlternativeことSupabaseについて紹介しました。

Firebaseでは毎度SNS認証だけ使用して、メインの機能であるRealtime Databaseを一切使用しないということをしていましたが、これからはその認識を改めざるを得ないかも知れないです。

最後までお読みいただきありがとうございました!