GASの業務システムの限界に挑戦する


2020年から5年間、ひとりCTOとして、とある事業者の業務システムとしてSEM広告の効果測定システムをGAS上で開発しています。 日々増えていく機能に合わせて、大小のリアーキテクチャを繰り返し実践し、クライアントの要望に応えてきました。

そのリアーキテクチャの一つとして、信頼できるデータソースとしてGoogleスプレッドシートからGoogle Drive のJSONファイルを扱うようにし、 データソースをGASの貧弱なリソース内で極力扱わずに、フロントエンドにデータを持ち込み処理をするスタイルへの移行があります。

今回は、なぜデータソースの読み取りを分離するアプローチを採用し、どのように課題解決してきたのか、また得られた知見について共有したいと思います。

1. 背景

この効果測定システムは、広告出稿データと成果データを突き合わせて、CVRやCPAなどの指標を日毎や任意の集計日時にて算出表示するシステムになっています。 リアーキテクチャ以前の段階では、基本的に以下のような限定された機能を持っていました。

  1. 広告出稿データと成果データを紐付け
  2. スプレッドシートに表示する
  • 1案件(100~3000+行 x ~200+列 x ~30+シート) x 複数案件スプレッドシート
  1. スプレッドシートに集計されたデータを表示する

この時点で、システム上でフロントエンドを利用したシートごとの分割並列実行などを実施していました。

ただし、機能が増えていくにつれ、以下のような要望や技術的な課題がありました。

  • データ量が増えて、スプレッドシートへの書き込み読み取りが単純に遅い
  • 整形されたスプレッドシートをデータソースとして再集計しており、指標の追加が難しい
  • 信頼できるデータソースとして参照先を増やさざるを得なくなった
  • 機能拡張に従って集計済みデータの必要性や高頻度化、またその書き込み先が増大・多様化した

移行の決断に至ったのは、データソースとしてのスプレッドシートおよび補足的な情報ソースを参照するだけでは、 スプレッドシートの運用も加味して、データの信頼性を担保しきれず整合性を保てない可能性が残るような機能追加が発生したタイミングでした。

2. リアーキテクチャ

改めて課題を整理すると、データソースの分散集計出力先の増加と速度低下 を意識しつつ負債を溜めながら開発を継続していたことでした。 それが既存の運用スタイルだとデータソースの整合性を損なうようになる機能追加が発生してしまいました。具体的には、データソースとしてのスプレッドシートは運用上破棄する可能性がありましたが、その破棄以上のデータを集計表示する要件が必要になったのでした。

この問題を解決するために、1. 信頼できるデータソースの構築 -JSONファイルベース, 2.増加する集計要件への対応 -フロントエンドでのキャッシュ です。

予め補足すると、クラウドの利用は制限されます。提案することもしましたが、実現には至りませんでした。 DB系は特に維持コストもかかるので、数字やROIがシビアに求められるWeb広告の分野では理解できるところです。 データは、1案件1年分で十数MBで、改めてクラウド上でのコストの計算やゼロコスト構成も考えられますが、私としても十分枯れて運用コストの極めて低い Google Drive も十分メリットはあると思っています。

2-1. 信頼できるデータソースの構築 -JSONファイルベース

信頼できるデータソースとしてJSONファイルを利用して、すべての指標をファイルに一元化しました。

同時書き込みは運用上ほとんどありえませんが、補助的な排他制御として、案件ごとのプロパティストアへのロックを利用して、操作中であれば適当に弾く処理を追加しています。 また、簡易的なバックアップも用意して、万が一の実行エラーやマニュアルでのデータ欠損やファイル削除に保険を掛けています。

2-2. 2.増加する集計要件への対応 -フロントエンドでのキャッシュ

フロントエンドから各タスクを並列する従来スタイルに加えて、合わせてデータソースを初期化時に読み込み、並列タスクに対してそれぞれ付加するアプローチを取っています。

個別のタスク毎について、GAS上でスプレッドシートへの書き込みする際に、必ずDriveのJSONファイルを読むのは必要以上のコストです。 初期化時の読み取り専用のデータについては、フロントエンドから整形済みのデータを最小限で流して、GAS上では書き込みのみに専念するようにしました。 読み取り専用データの整合性については、運用上の都合もあり実現可能になった点はあると思います。

初回読み取りや各並行処理でのフロントエンドとバックエンドの通信量の増大は、コストとして存在しており、各通信毎にGzip化するなどの地味な改善も行っています。

また、フロントエンドでJSONファイルをクエリする場合、ライブラリやDuckDBを利用する可能性も考慮しましたが、利用しませんでした。 これは、すでにビジネスロジックが維持できていたこと、バックエンド単体での同様のクエリが存在していることを加味した判断です。

3. リアーキテクチャの移行ステップ

1年かけてデータソースのJSONへの保存との並行、部分的なフロントエンドへのキャッシュ対応などから始まり、 機能追加やバグ修正の間に挟み込み、完全なレガシーデータソースからの脱却と、完全移行対応が完了しました。

4. リアーキテクチャ後の課題

今後、JSONファイルの容量の増大で動かなくなると思っています。 解決策のヒントとして、利用するのは特に数週間程度、多くても半年程度あれば十分な点に注目しても良いかもしれません。 このあたりはクライアント相談しつつにはなりますが、今後、一定期間のアーカイブや、キャッシュストアの活用も検討していくことになると思っています。

また、依然としてスプレッドシートへの書き込みがあり、全体の実行時間が長くなっています。とくにクイックに確認したい用途などが出てきた場合には、UIにそのまま表示してしまう、というのも一つの手かもしれません。ただし、やはり運用者が慣れている書式でストレスなく分析できることは、毎日の指標動向を常に気にかけておられるので、とても大事なことだと思っています。

5. 初期開発から7年目を見据えて

これらのリアーキテクチャについては、クライアントへの説明も難しく、単独で勝手に初めたと思われなくもないと考えていました。 クライアントには、テキストや移行の簡単な図を使って説明できたのは良かったかなと思ってます。

過去にこのシステムについて「GAS ww」「JSONって負債ですよねww」 「チームではないのねww」と言われたことがあります。 ただ5年間、数千万円のWeb広告を集計し、実際に毎日の運用に役立てていただいている事実と、 その期待に答えるために、工夫をこらし要望を実現してきたことは、自信があります。 障害対応や細々したバグ修正はもちろん、今回紹介したようなリアーキテクチャ、自身のコード負債との向き合いなど、とても濃密で実のある開発経験だと思っています。

今後も、さらなる発展と安定運用に向けて、精進していきます。

以上!