SpreadSheet + GoogleCloudFunctions + Goで管理画面作った


つくったもの

サークルのホームページとその管理画面
(所属サークルがばれるのでURLは割愛)

要件

  • 無料で運用したい(サークルの経費節約💸)
  • 非エンジニアがHPを更新するので、データを入力する管理画面が必要
  • バックエンドはGoで書きたい

システム概要

管理画面

管理画面を作るのがめんどうだったので、非エンジニアでも使いやすいGoogleSpreadSheetを採用。

シート保護しまくってHP管理者がうっかり破壊してしまわないようにしておく。
また、データ入力範囲に名前をつけておく。

GASに紐づいたボタンを設置。
GASではシンプルにGoogleCloudFunctionsの呼び出しのみを行う。


function updateHoge() {
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var id = ss.getId();

    UrlFetchApp.fetch("https://~.cloudfunctions.net/hoge?sheetID=" + id, {"method": "put"});
}

HP管理者はデータ入力して更新ボタンをポチッとすれば、HPにデータが反映される👏

FaaS

GASに書いてしまうこともできるが、スクリプトエディタのコード補完が微妙で書きにくい、、、😖
GASではトリガーを引くだけにして、処理はGoogleCloudFunctionsに置くことにした。
GoogleCloudFunctions採用理由は以下の通り。

  • SpreadSheetへのアクセスが簡単(サービスアカウント)
  • FaaSなので難しいこと考えなくて良い!
  • Goランタイムがリリースされた🎉Goが書ける!!

func Hoge(w http.ResponseWriter, r *http.Request)型の関数をデプロイすることができる。
Goのnet/httphttp.HandleFunc等に渡す関数と同じ型なので、ローカル実行も簡単。
トリガーはHTTPリクエストにする。
以下のコマンドで、関数Hogeを登録名hogeとしてデプロイできる。

gcloud functions deploy hoge --entry-point Hoge --runtime go111 --trigger-http

以下のようにMethodで条件分岐しておくと、Methodごとの動作を変えられる。
こうしておくと通常のサーバと同じような振る舞いができる。
例) curl -X GET ~~~/hoge -> データ読み出し
curl -X PUT ~~~/hoge -> データ書き込み

func Hoge(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case "GET":
        // データを取得する関数
    case "PUT":
        // データを保存する関数
    }
}

GETでは、Firestoreからデータを取得して返す。
PUTでは、SpreadSheetの名前をつけた範囲からデータを抽出し、Firestoreに保存する。

DB

SpreadSheetをDBとして扱うこともできるが、入力途中のデータがHPに公開されるとまずいので、別途DBを用意。

Firestoreを採用。使ってみたかった。
良い感じのデータ構造を考える。

クライアント

お好みの技術で最強にかっちょいいHPを作って、Firebase Hostingで配信。

GoogleCloudFunctionsのURLにGETリクエストを送って、データを受け取る。

感想

  • GoogleCloudFunctionsで関数ごとにデプロイするのが少し面倒。
    • コード変更箇所がどの関数に影響するか考えてデプロイするのが面倒だったので、一括デプロイコマンドを作った。
  • 全部Googleのサービスで作ったので、各サービスの接続が簡単だった(サービスアカウント)。
  • SpreadSheetを管理画面にしたことで、データのコピペや並べ替え機能を容易に提供できた。

あとがき

もともとFirebase,React,Goでのweb開発の勉強がしたくて、サークルのHPを題材に選んだが、管理画面が必要な経緯でGoogleCloudFunctionsも学べて花まる大満足💮