試して、戻す——設計原則が判断を速くする

LINE OGPへの対応をCloudflare Workerで試み、
プラットフォームの制約を発見し、半日で全コードを元に戻した。
判断が速かったのは、能力ではなく設計原則のおかげだ。

この記事で言いたいこと:TokiQRのplay.htmlをLINEで共有した際にカスタムサムネイルを表示しようと、Cloudflare Workerを拡張してOGP対応を実装した。しかしLINEはコンパクトカード表示しかサポートしておらず、カスタムサムネイル画像は表示されなかった。短縮URLという回避策は技術的に可能だったが、「データはURL内に自己完結する」という設計原則に反するため即座に棄却した。コードを書き、デプロイし、テストし、戻す。この一連が半日で完結したのは、原則が判断を代行したからだ。

1. やりたかったこと

TokiQRのplay.htmlは、QRコードに記録された音声・画像・テキストを再生するページだ。URLパラメータにすべてのデータが含まれている。サーバーへの問い合わせは一切ない。

このURLをLINEで送ったとき、リッチなサムネイル——タイトル、説明文、カスタム画像——が表示されれば、受け取る側の体験が良くなる。OGP(Open Graph Protocol)のメタタグをクローラーに返せば実現できるはずだった。

実装したこと

既存のCloudflare Worker(52行のGASプロキシ)にOGP機能を追加した。ロジックは明快だ。

URLパラメータからデータ種別(音声・画像・テキスト)を判定し、適切なOGPタイトルと説明文を生成する。Codec2音声の場合はBase64長から秒数まで計算して「14.0秒の音声メモリー」のように表示する。OGP画像も3種類作成した。

実装は完了し、Cloudflareにデプロイし、play.jsのシェア機能をWorker URL経由に切り替えた。curlでテストすると、クローラーUAには正しくOGP HTMLが返り、通常UAには302リダイレクトが返った。技術的には正しく動作していた。

2. 何が起きたか

LINEで実際にURLを送信した結果、OGPのタイトルと説明文、そしてアイコン画像は正しく表示された。しかし、カスタムサムネイル画像——1200x630pxのリッチな画像——は表示されなかった。

LINEのURL共有では、コンパクトカード(小さなアイコン+タイトル+説明文)しか表示されない。og:imageに指定した大きな画像は、LINEのプレビューカードには反映されない仕様だった。

これはバグではない。LINEというプラットフォームの設計判断だ。

加えて、play.htmlのURLは最大4000文字近くになる(Base64エンコードされた音声データがパラメータに含まれるため)。この長さのURLがLINEのメッセージに貼り付けられると、URL自体がメッセージの大部分を占め、サムネイル以前の問題として見栄えが悪い。

3. 短縮URLという誘惑

技術的な解決策は存在した。Cloudflare Workers KV(Key-Value Store)を使って短縮URLを実装すれば、4000文字のURLを20文字程度に圧縮できる。LINEのメッセージも綺麗になる。

しかし、この解決策は設計原則に正面から反する

TokiQRの核心は、データがURLパラメータとして自己完結していることだ。サーバーに問い合わせる必要がない。QRコードをスキャンし、ブラウザで開くだけで音声が再生される。CloudflareもGASもGitHubも関係ない。

短縮URLを導入した瞬間、この自己完結性が崩れる。短縮URLのマッピングはCloudflare KVに保存される。KVが消えたら、短縮URLは永久にデッドリンクになる。データの永続性を、外部サービスの寿命に委ねることになる。

短縮URLは便利だ。しかしそれは、4000文字のURLに込められた自己完結性を、20文字の外部依存に置き換える行為だ。

前回のエッセイ「CloudflareとGAS——使うことと、頼ることは違う」で定義した原則がここで機能した。運用レイヤーは外部に依存してよいが、永続レイヤーは何にも依存してはならない。短縮URLは永続レイヤーの問題だ。だから却下した。

4. 原則が判断を代行する

短縮URLの却下は即座だった。検討に要した時間はほぼゼロだ。

これは判断力の問題ではない。原則が判断を代行したのだ。

設計原則が明確に言語化されていれば、新しい問題に直面したとき、考える必要がない。原則に照らすだけで答えが出る。

問い 原則との照合 判断
短縮URLを導入するか? 永続レイヤーが外部KVに依存する 却下
OGP Worker自体を維持するか? LINEの制約で目的を達成できない 全コードを戻す
noindexは戻すか? 個人データURLの検索インデックスは不要 noindexだけ残す

3つの判断すべてに迷いがなかった。原則が明確だからだ。原則がなければ、「短縮URLにすれば見栄えが良くなるし、とりあえず入れておこうか」という議論が始まっていただろう。そしてその議論は、技術的な実現可能性やユーザー体験やコストの話に分岐し、何時間もかかったかもしれない。

5. 試すことの価値

この一連の取り組みは無駄だったか。そうは思わない。

試す前には分からなかったことがある。LINEがカスタムサムネイルを表示しないこと。play.htmlの長大なURLがLINEのメッセージで視覚的に破綻すること。これらは実装してデプロイしてテストして初めて分かった事実だ。

そして、試したからこそ戻す判断に確信が持てた。「LINEがサムネイルを出せないらしい」という伝聞と、「自分で実装してデプロイして確認した結果、出ない」という経験では、判断の重みが違う。

加えて、OGP対応の過程でplay.htmlnoindexを追加するという副産物が得られた。個人の音声データを含むURLが検索エンジンにインデックスされる必要はない。これは試みの中で自然に浮かんだ改善であり、OGPとは無関係に価値がある。

半日の時系列

ステップ 内容
計画 Cloudflare Worker OGPプロキシの設計
実装 Worker拡張、OGP画像3枚生成、play.js修正
デプロイ Cloudflareにデプロイ、curlで動作確認
検証 LINEで実際に送信、カスタムサムネイル非表示を確認
判断 短縮URL却下、全コードrevert、noindexだけ残す
復旧 Worker・play.js・OGP画像をすべて元に戻す

6ステップが半日で完結した。「戻す」という判断に時間がかからなかったのは、原則が明確だったからだ。そして「戻す」という実作業に時間がかからなかったのは、Gitがあったからだ。

6. 結び——原則は判断のキャッシュだ

設計原則は、判断のキャッシュだ。

一度深く考えて言語化しておけば、
次から同じ問いに即座に答えられる。

設計原則が明確でないプロジェクトでは、同じ種類の判断が何度も議論される。「外部依存を増やしていいのか」「ユーザー体験のためなら許容するのか」「一時的なら問題ないのか」。毎回ゼロから議論するのは時間の浪費だ。

トキストレージでは「永続レイヤーは外部に依存しない」と言語化してある。だから短縮URLは即座に却下できた。OGP対応は目的を達成できないと分かった瞬間に全コードを戻せた。判断のたびに立ち止まる必要がなかった。

試して、原則に照らして、戻す。この循環を高速に回せることが、設計原則の実践的な価値だ。原則は理念ではなく、判断を加速する道具だ。

関連エッセイ