1. なぜ環境について考えるのか
一般的なウェブ開発では、遅かれ早かれ「ローカル開発・テスト用サーバ・production 環境」という三点セットが現れます。ChatGPT Apps の世界でも同じですが、ひとつ重要なひねりがあります。クライアント(ChatGPT)は 常にクラウド上 にあり、たとえあなたが「ローカルで」開発しているときでも同じです。
もしすべてがあなたのノートPC上でランダムなトンネルのアドレスだけで回っていると、いくつか厄介な問題が生じます。第一に、URL が常に変わり、Dev Mode が今どのエンドポイントにひも付いているかを覚えていられません。第二に、パフォーマンスやネットワークは本番と似ても似つきません。第三に、ローカル環境では別のキーや別のサービスを使いがちで、まるで平行世界のように生きています。
一方で「常に本番で暮らす」のも良くありません。ちょっとした修正が、生のユーザーのシナリオを突然壊すことがあります。とくに Stripe や OAuth、ACP などの決済統合がある場合はなおさらです。法務やポリシーの観点でも問題になりがちで、実ユーザーで実験するのは Store に出すうえで最善の道ではありません。
そこでこの講義の目標は、シンプルだが強固な枠組みを頭に入れることです。つまり local dev、staging、production があり、Dev Mode は ChatGPT を必要な環境へ向けるための手段である、ということ。ランダムなトンネルの「マイPC」が時々突然本番に化ける、という「巨大なひとつの世界」にしないことです。
2. ChatGPT Apps の特徴: クライアントは常にクラウド
典型的な SPA アプリでは、クライアントもサーバもローカルで動かすことがよくあります。ブラウザは localhost、バックエンドも localhost、同一マシン内で幸せに会話します。
しかし ChatGPT Apps ではそうなりません。クライアント(ChatGPT + あなたのウィジェット)は常に OpenAI のインフラ上にあります。アプリのコードがあなたのノートPCで動いていても、リクエストは次のように流れます:
sequenceDiagram
participant User as ユーザー
participant ChatGPT as ChatGPT (クラウド)
participant Tunnel as HTTPS トンネル
participant App as あなたの Next.js + MCP
User->>ChatGPT: メッセージ / ウィジェットのクリック
ChatGPT->>Tunnel: アプリのURLへのHTTPSリクエスト
Tunnel->>App: localhost へのプロキシ
App-->>Tunnel: 応答 (UI/JSON)
Tunnel-->>ChatGPT: 応答
ChatGPT-->>User: 更新されたチャット + ウィジェット
「ローカルで軽くテストしているだけ」のときでさえ、あなたはすでに分散システムの中にいます。クラウドのクライアント、ネットワーク、トンネル、ローカルサーバが存在します。
重要な理由:
- ローカル環境は「全部ローカル」では ありません。それは「クラウド → トンネル → ローカルサーバ」です。
- のちに staging と production を追加しても、違いは ChatGPT がどこにリクエストを送るかだけです。トンネルか、staging ドメインか、本番ドメインか。
3. Local dev: 現在の構成はどう見えるか
この全体像が今あなたの手元でどうなっているか見てみましょう。
モジュール 2〜6 を終えた段階では、おそらく次のような構成です:
- npm run dev で起動した Next.js の dev サーバ(通常は http://localhost:3000)。
- ローカルの MCP サーバ(多くは別プロセス。例: http://localhost:2091)。
- HTTPS トンネル(ngrok、Cloudflare Tunnel など)。Next.js/HTTP エンドポイントを https://abc123.ngrok.app のような公開 URL に出します。
ChatGPT の Dev Mode でこの公開 URL を指定すると、ChatGPT はあなたのアプリにアクセスし始めます。これが local dev 環境 です。
local dev の主な特性:
- ローカルはフィードバックループが非常に速い。VS Code でコードを変えると Next.js がホットリロードし、ウィジェットは数秒で更新されます。
- 何でも壊してよい。モックデータ、テスト用キー、変わった設定も自由です。
- 実ユーザーはいません。あなた以外はその URL をほぼ知りません。
見た目はだいたいこんな感じです:
graph LR
subgraph Dev Laptop
Next[Next.js dev server]
MCP[MCP server]
end
ChatGPT((ChatGPT Cloud))
Tunnel[[HTTPS トンネル]]
ChatGPT --> Tunnel --> Next
Next --> MCP
local/staging/production の取り違えを防ぐには、アプリ自身が「今どの環境で動いているか」を把握できるようにしておくと便利です。コード上でも、今は dev 環境であることを明示しておくとよいでしょう。最も簡単な一歩は、小さな環境設定モジュールを導入することです。
たとえば、app/config/env.ts を作成します:
// app/config/env.ts
export type AppEnv = 'local' | 'staging' | 'production';
export const APP_ENV: AppEnv =
(process.env.NEXT_PUBLIC_APP_ENV as AppEnv) ?? 'local';
export const isProd = APP_ENV === 'production';
ここでは次を行っています:
- 環境の型付き列挙を導入する。
- NEXT_PUBLIC_APP_ENV という環境変数を読む(後で dev/staging/prod で異なる値を設定します)。
- デフォルトを 'local' にして、ローカル開発が「箱出し」で動くようにする。
これはまだ何もデプロイしませんが、コードがどの環境で実行されているかを理解できる出発点を与えてくれます。
次に、混同を避けるためウィジェットそのものに環境を表示してみましょう。
// app/components/EnvBadge.tsx
import { APP_ENV } from '../config/env';
export function EnvBadge() {
return <span>ENV: {APP_ENV}</span>;
}
この小さなバッジは、ウィジェットの見た目が同じでも「今は staging か? それとも本番か?」を取り違えないのに大いに役立ちます。
4. Staging: production の総合リハーサル
staging 環境は「production 環境のリハーサル」です。もはやあなたのノートPC上の dev サーバではなく、ビルド済みコードが配置されるリモートサーバや Vercel のデプロイになります。
ChatGPT から見ると staging はほぼ production と同じです。例えば https://staging.giftgenius.app のような、使いやすく安定した HTTPS エンドポイント(ドメイン)で、以下のような特徴があります:
- コードはビルド済み(npm run build が正常終了)。
- 本番に近い環境変数(同じ名前・同じ形式)だがテスト用のキーを使う。
- 外部サービスも同等(Stripe sandbox、テスト用 OAuth アカウントなど)。
- ネットワークトポロジーも本番に近い(同じ種類の DB、同じリージョンなど)。
ChatGPT Apps の文脈で staging が必要な理由:
第一に、staging はエンドツーエンドのシナリオを回すのに最適です。例: ChatGPT 内のユーザー → ChatGPT があなたのアプリを起動 → ウィジェットがユーザーに質問 → 外部 API を呼ぶ MCP ツールを実行 → レコメンドを返す → ウィジェットが結果を表示。こうしたシナリオは、ローカルのランダムなトンネル越しだとある振る舞いをし、staging だと別の振る舞いをすることがあります。staging の方がレイテンシやネットワーク、リソースが現実に近いからです。
第二に、ローカルでは怖くて動かしづらい統合のテストができます。たとえば決済(Stripe、ACP/Instant Checkout など)。staging ではテストキーやテスト用の Webhook を設定し、「本番さながら」にシナリオを回せますが、実際のお金は動きません。
第三に、staging はチームでの動作確認の場です。複数の開発者、デザイナー、QA、プロダクト担当がいるなら、誰かのノートPCやトンネルの稼働状況に依存しない共通の URL が必要です。
staging は次のように捉えるとわかりやすいでしょう:
graph LR
ChatGPT((ChatGPT Cloud))
AppStaging["GiftGenius Staging https://staging.giftgenius.app"]
ChatGPT --> AppStaging
https://staging.giftgenius.app の内部では、Next.js、MCP サーバ、staging 用の DB などが動いているかもしれません。
この講義では Vercel へのデプロイ詳細には入りません(それは後続のトピックです)。ここで重要なのは、staging が production に最大限似せた別環境であり、ChatGPT がそこへ到達する経路も production と同様に安定している、という事実です。
5. Production: 本番サーバと実ユーザー
production 環境は、実ユーザーと 実際のお金 が関わる場所です。ここでは「main をちょっと直して様子を見る」といったことは通用しません。あらゆる変更は意図的で、テスト済みで、可能ならロールバック手段があるべきです。
production ドメインは安定していなければなりません。ランダムな ngrok の URL ではなく、https://giftgenius.app のような正規のドメインです。Store の App 設定にもこのアドレスを指定します。ユーザーが ChatGPT Store であなたのアプリを見つけて起動すると、ChatGPT はこのエンドポイントを呼びます。
production 環境には通常、より高い要件があります:
- 安定性。 低いエラー率、予測可能な応答時間、負荷下での正しい動作。後続モジュールで SLO/SLI について述べますが、直感的には「アプリは“ほとんど常に”動作し、“ほとんど常に”速く応答する」ことです。
- セキュリティ。 必要なシークレットだけ、最小限の権限、PII や金銭の慎重な取り扱い。
- 実験の制限。 営業時間中に「また dev サーバを再起動した」などは厳禁。実験はフィーチャーフラグや A/B、あるいは専用の dev/staging 環境で行い、本番サーバを直接いじらないこと。
ChatGPT の観点では、production はもはや Dev Mode の話ではなく、公開済みの App の話です。Store や組織設定を通してユーザーに提供され、レビューを通過し、モデレーションの前で恥をかかないだけの信頼性が必要です。
6. Dev Mode と本番利用の App: 何にひも付くのか
よくある誤解として、ChatGPT の Dev Mode を「別の環境」と見なすものがあります。しかし実態は、Dev Mode は ルーティングのスイッチ に過ぎません。あなたがアプリをテストするとき、ChatGPT がどの URL を見るかを切り替える機能です。
Dev Mode では次のことができます:
- トンネル経由でローカルアプリを接続する。
- staging 環境を接続する。
- 一時的に Dev Mode を production に向ける(通常は非推奨)。
形式的には、Dev Mode は ChatGPT に「これが私の App のマニフェストで、これが私の MCP/Apps SDK エンドポイントの URL。私がこのアプリを起動したらこれを使ってね」と伝えます。そしてその URL はあなたが変更できます。
Store に公開すると、App には公式の production エンドポイントが付きます。実ユーザーにはそれが使われ、勝手に変更することはできません。新しいバージョンやレビューが必要になります。
学習用アプリにおける現実的な構成例は次のとおりです:
graph TD
subgraph Dev Mode
DevApp["GiftGenius Dev App
(Dev Mode)"]
end
subgraph Store
ProdApp["GiftGenius
(Store App)"]
end
UserDev[あなた / チーム] --> DevApp
UserProd[実ユーザー] --> ProdApp
DevApp -->|トンネルのURL| LocalEnv[Local dev
https://abc123.ngrok.app]
DevApp -->|staging URL| StagingEnv[Staging
https://staging.giftgenius.app]
ProdApp -->|prod URL| ProdEnv[Production
https://giftgenius.app]
Dev Mode の GiftGenius Dev は、通常は local dev(トンネル経由)を向くように設定し、必要に応じて staging に切り替えます。Store の GiftGenius は production の URL にのみ固定されます。
場合によっては QA 用の別 App(例: GiftGenius Staging)を作り、常に staging の URL のみを見るようにすることもあります。大人数のテストチームがいるなら便利ですが、この講義では 1 つの dev 用 App で十分です。
大切なのはこう考えることです。Dev Mode はあなたやチームのためのサンドボックスで、URL を変えたりメタデータを直したりトンネルを再起動したりできます。一方で Store の production 用 App は production のみに向き、より厳格なルールで運用されます。
7. Git ブランチ、ドメイン、ChatGPT App のひも付け
環境とはサーバだけではありません。コードのブランチ や、ChatGPT 側の App 設定 も含みます。いつかきっと、URL や App 名をひと目見ただけで、そこで動いているコードのバージョンがわかるようにしたくなります。
最小のシンプルな方針は次のとおり。
個々の機能開発には feature/* ブランチ(例: feature/new-recommendation-algo)を使います。コードはローカルで実行し、トンネル経由で公開。ChatGPT の Dev Mode は通常、同じ dev エンドポイントを見ており、そこでローカル版を順に動かします。機能ブランチごとに別の App を作るのはやり過ぎです。
リリース前の機能統合には、develop や staging ブランチを用意してもよいでしょう。このブランチの内容は自動で staging 環境にデプロイされ、たとえば https://giftgenius-staging.vercel.app のような Vercel のプレビュー URL になります。これに対して別の Dev Mode 用 App を作るか、共通の Dev 用 App をその URL に都度向け替える方法があります。
main(または master)ブランチは、テスト済みコードのみです。これだけが production の URL にデプロイされ、Store の GiftGenius にひも付きます。
概ね次のようになります:
| 環境 | Git ブランチ | URL | ChatGPT App |
|---|---|---|---|
| Local dev | |
|
GiftGenius Dev (Dev Mode) |
| Staging | |
|
GiftGenius Dev または GiftGenius Staging |
| Prod | |
|
GiftGenius (Store) |
app/config/env.ts の APP_ENV を覚えていますか。ここでの 'local'/'staging'/'production' は、表の「環境」列と 1 対 1 に対応します。local dev では APP_ENV=local、staging デプロイでは APP_ENV=staging、production では APP_ENV=production で起動します。
この表は単なるお作法ではなく、「このドメインでは今どのバージョンが動いているの?」という手探りデバッグを避けるための手段です。
コード側でもこのひも付けを少し強化できます。たとえばウィジェットのデバッグ表示で ENV だけでなく、コミットやブランチも表示します:
// app/config/buildInfo.ts
export const BUILD_COMMIT = process.env.NEXT_PUBLIC_BUILD_COMMIT ?? 'dev';
export const BUILD_ENV = process.env.NEXT_PUBLIC_APP_ENV ?? 'local';
// app/components/BuildInfo.tsx
import { BUILD_COMMIT, BUILD_ENV } from '../config/buildInfo';
export function BuildInfo() {
return <small>Build: {BUILD_ENV}@{BUILD_COMMIT}</small>;
}
デプロイ時に NEXT_PUBLIC_BUILD_COMMIT にコミットの SHA を流し込めば、ウィジェットに今動いているコードの正体が正直に表示されます。staging/production では、これが何時間ものデバッグ時間を救ってくれることがあります。
8. ミニ実践: 自分の環境図を描こう
Vercel やログの話に進む前に、文字どおり「紙ナプキンに」自分の環境図を描いてみると有益です。これは README.md の mermaid 図でも、ホワイトボードの走り書きでも、ノートの図でも構いません。
学習用の GiftGenius なら、図は次のようになります:
graph TD
subgraph ChatGPT
DevMode["Dev Mode
(あなたとチーム)"]
Store["Store
(実ユーザー)"]
end
subgraph Servers
Local[Local dev
Tunnel → localhost]
Staging[Staging
staging.giftgenius.app]
Prod[Production
giftgenius.app]
end
DevMode --> Local
DevMode --> Staging
Store --> Prod
講義後すぐにできる有益な練習:
- すでにある 環境をすべて書き出す。トンネル付きのローカル、初期の Vercel デプロイなど。
- その隣に、どの Git ブランチがどこへデプロイされるかを書き添える。
- さらに隣に、どの ChatGPT Apps(またはコネクタ)がどこを向いているかを書き添える。
- ChatGPT が各サーバへどこから到達するか、矢印で示す。
単独開発でないなら、リポジトリに architecture/environments.md を用意して同じことを書きましょう。「staging が落ちたが、そもそも URL がわからない」といった確率を一気に下げられます。
アプリと結び付けるため、Dev Mode で App をひとつ(GiftGenius Dev)作り、デフォルトではローカル環境のトンネルを向け、リリース全体を試したいときだけ一時的に staging の URL に向け替える、という運用にしておくとよいでしょう。次の講義では、Vercel への staging/prod デプロイと環境変数とのひも付けを学びます。
要するに、環境と Dev Mode をあなたの App の座標系として扱ってください。ローカルは高速な開発のため、staging は総合リハーサルのため、production は実ユーザーのため。そして Dev Mode はそれらの間を切り替えるスイッチであって、独立した魔法の環境ではありません。
9. 環境と Dev Mode でよくある誤り
エラー1: localhost + トンネルだけで生きて、それを本番だと思い込む。
このやり方は一見便利です。「staging も prod もいらない。トンネルは動いてるし、ChatGPT はつながるし」。しかしトンネルの URL は不安定で、ネットワーク特性も異なり、全体が 1 台のノートPCに依存します。OAuth のコールバック、Stripe の Webhook、MCP Gateway のようなものが必要になった途端、ちゃんとした staging/prod がないことが痛みになります。
エラー2: Dev Mode を独立した環境と取り違える。
「Dev Mode がある=dev 環境がある」と考えがちですが、実際には Dev Mode は ChatGPT に「どこへ行くか」を指示するだけです。トンネルか、staging か、あるいは本番か。Dev Mode はクライアント側の設定であって、サーバ側の環境ではありません。サーバ側の環境(local/staging/prod)はあなたが用意します。コードをデプロイし、ドメインを設定し、環境変数を整えるのです。
エラー3: Dev Mode を production に向けて「ちょっとテスト」する。
技術的には可能です。Dev Mode に production の URL を入れれば、ローカルのように App で遊べます。しかしその瞬間、あなたは実ユーザー・実データ・場合によっては実際のお金でテストを始めてしまいます。ツールやウィジェットのささいなミスが本番ユーザーの障害につながり、原因の特定も難しくなります。Dev Mode は dev/staging に向け、production は Store の App を使う方が賢明です。
エラー4: 「ブランチ ↔ 環境 ↔ URL ↔ App」の地図が明示されていない。
チームの誰もが、staging にどのブランチがデプロイされ、URL が何で、どの ChatGPT の App がそれを向いているかを即答できないなら、混乱は必至です。「自分の手元では動く、staging では動かない、本番ではまた別」といった話が始まります。単純な表や markdown の地図は、コスト以上の価値を返してくれます。
エラー5: local dev と staging の違いを過小評価する。
ローカルでは dev サーバで動き、キーもサービスもネットワークも 1 セットです。staging ではコードはビルド済みで、別の環境で、別の制限・タイムアウト・ルーティングで動きます。すべてをローカルだけでテストし、staging を「形だけ」にしていると、致命的なバグは本番で露呈します。流れに慣れましょう。まずローカル開発、次に staging で検証、そして最後に production リリースです。
エラー6: 環境の構図を無視して、問題をすべて ChatGPT で解決しようとする。
問題が起きたとき、開発者が「ChatGPT に何が起きたか聞く」ことから始めてしまうことがあります。その前に、図を見ましょう。どの App がどの URL にひも付き、どの環境で落ち、ログはどこか。今日の環境の枠組みは、次の講義(ログを見る、MCP インスペクターを使う、そして最後にモデルを疑う)に向けた土台です。
GO TO FULL VERSION