CodeGym /행동 /ChatGPT Apps /환경: local dev, staging, production + Dev Mode

환경: local dev, staging, production + Dev Mode

ChatGPT Apps
레벨 7 , 레슨 0
사용 가능

1. 왜 환경을 고려해야 할까

일반적인 웹 개발에서는 결국 세 가지가 생깁니다: 로컬 개발, 테스트 서버, 그리고 production 환경. ChatGPT Apps 세계도 동일하지만 한 가지 추가 포인트가 있습니다. 클라이언트(ChatGPT)는 항상 클라우드에 있으며, 심지어 여러분이 “로컬에서” 개발할 때도 그렇습니다.

모든 것이 여러분의 노트북에서 임의의 터널 주소로만 돌아가면 몇 가지 불편한 점이 생깁니다. 첫째, URL이 계속 바뀌어 Dev Mode가 지금 정확히 어떤 엔드포인트에 연결되어 있는지 기억하기 어렵습니다. 둘째, 성능과 네트워크가 실제 운영 환경과 다릅니다. 셋째, 로컬 환경은 종종 다른 키, 다른 서비스들을 사용하며 전반적으로 별도의 평행 세계처럼 동작합니다.

반대로 “항상 프로덕션에서만” 살 수도 없습니다. 어떤 수정이든 실제 사용자 시나리오를 갑자기 깨뜨릴 수 있고, 특히 Stripe, OAuth, ACP 결제 같은 통합이 있다면 더욱 그렇습니다. 법적/정책적 관점에서도 문제입니다. 실제 사용자에게서 실험하는 것은 Store 출시를 위한 최선의 길이 아닙니다.

그래서 이 강의의 목표는 머릿속에 간단하지만 엄격한 도식을 세우는 것입니다. local dev, staging, production이 있고, Dev Mode는 ChatGPT를 원하는 환경으로 보낼 수 있는 스위치라는 점이죠. 즉 “가끔 갑자기 프로덕션으로 변하는 내 터널 달린 노트북”이 아닌 체계적인 구성을 갖추는 것입니다.

2. ChatGPT Apps의 특징: 클라이언트는 항상 클라우드에 있음

전통적인 SPA 애플리케이션에서는 클라이언트와 서버를 로컬에서 함께 띄우는 일이 흔합니다. 브라우저는 localhost, 백엔드도 localhost에 두고 한 머신 안에서 행복하게 통신하죠.

하지만 ChatGPT Apps에서는 그렇지 않습니다. 클라이언트(ChatGPT + 여러분의 위젯)는 항상 OpenAI 인프라에 있습니다. 설령 애플리케이션 코드가 여러분의 노트북에서 돌아가더라도, 요청 흐름은 다음과 같습니다.

sequenceDiagram
    participant User as 사용자
    participant ChatGPT as ChatGPT (클라우드)
    participant Tunnel as HTTPS 터널
    participant App as 당신의 Next.js + MCP

    User->>ChatGPT: 메시지 / 위젯 클릭
    ChatGPT->>Tunnel: App URL로 HTTPS 요청
    Tunnel->>App: localhost로 프록시
    App-->>Tunnel: 응답 (UI/JSON)
    Tunnel-->>ChatGPT: 응답
    ChatGPT-->>User: 업데이트된 채팅 + 위젯

즉 “그냥 로컬에서 테스트”할 때도 이미 분산 시스템 속에 있습니다. 클라우드 클라이언트, 네트워크, 터널, 그리고 여러분의 로컬 서버가 존재하죠.

왜 중요할까:

  1. 로컬 환경은 절대 “모두 내 로컬”이 아닙니다. “클라우드 → 터널 → 로컬 서버”입니다.
  2. 나중에 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 같은 주소로 외부에 공개.

ChatGPT의 Dev Mode에서 이 공개 URL을 지정하면 ChatGPT가 애플리케이션에 접근하기 시작합니다. 이 모든 것이 local dev 환경입니다.

local dev의 핵심 특성:

  • 로컬 환경은 매우 빠른 피드백 루프를 제공합니다. VS Code에서 코드를 바꾸면 Next.js가 hot reload 하고 위젯이 몇 초 내로 갱신됩니다.
  • 아무거나 마음껏 망가뜨려도 되고, mock 데이터, 테스트 키, 별난 설정을 써도 됩니다.
  • 실제 사용자는 없고, 여러분 외에는 이 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';

여기서 우리는:

  1. 타입이 있는 환경 열거를 도입합니다.
  2. NEXT_PUBLIC_APP_ENV 변수를 읽습니다(이 값은 나중에 dev/staging/prod마다 다르게 설정합니다).
  3. 기본값을 'local'로 두어 로컬 개발이 “바로” 동작하게 합니다.

아직 배포에 영향은 없지만, 코드를 전개할 기준점을 제공합니다. 코드가 현재 어떤 환경에서 실행되는지 이해하게 되는 것이죠.

다음으로, 헷갈리지 않도록 위젯에 현재 환경을 표시할 수도 있습니다.

// app/components/EnvBadge.tsx
import { APP_ENV } from '../config/env';

export function EnvBadge() {
  return <span>ENV: {APP_ENV}</span>;
}

이 작은 배지는 “지금 staging인가, prod인가?”를 헷갈리지 않게 해 줍니다. 특히 위젯 외형이 동일할 때 유용합니다.

4. Staging: production 환경의 최종 리허설

Staging 환경은 “production 환경의 리허설”입니다. 더 이상 여러분의 노트북과 dev 서버가 아니라, 빌드된 코드를 올려두는 원격 서버나 Vercel 배포입니다.

ChatGPT 관점에서 staging은 거의 production과 같습니다. 예를 들어 https://staging.giftgenius.app 같은 안정적인 HTTPS 엔드포인트/도메인을 갖추고, 다음과 같은 특성이 있습니다:

  • 코드는 이미 빌드됨(npm run build가 성공적으로 완료됨);
  • 실제 운영과 유사한 환경 변수를 사용(이름과 형식은 동일하되 테스트 키 사용);
  • 동일한 외부 서비스 사용(Stripe sandbox, 테스트 OAuth 계정 등);
  • 네트워크 토폴로지가 운영과 유사(예: 같은 종류의 DB, 같은 리전).

ChatGPT Apps 맥락에서 왜 staging이 필요한가:

첫째, end-to-end 시나리오를 돌리기에 staging이 가장 적합합니다. 예: 사용자가 ChatGPT에서 시작 → ChatGPT가 앱을 호출 → 위젯이 사용자에게 질문 → MCP 툴이 외부 API 호출 → 추천 반환 → 위젯이 결과 표시. 이런 시나리오는 임의 터널을 통한 로컬에서는 한 방식으로 보이지만, staging에서는 지연, 네트워크, 자원이 현실에 더 가깝기 때문에 다르게 보일 수 있습니다.

둘째, 로컬에서 돌리기엔 부담스러운 통합(결제: Stripe, ACP/Instant Checkout 등)을 테스트할 수 있습니다. staging에서는 테스트 키와 테스트 웹훅을 설정하고 “제대로” 된 방식으로 시나리오를 검증하되, 실제 돈은 쓰지 않습니다.

셋째, staging은 팀 공동 검증의 무대입니다. 여러 개발자, 디자이너, QA, PM이 있다면, 누군가의 노트북 전원이나 터널 상태에 좌우되지 않는 공용 URL이 필요합니다.

staging을 이렇게 생각하면 편합니다:

graph LR
    ChatGPT((ChatGPT Cloud))
    AppStaging["GiftGenius Staging  https://staging.giftgenius.app"]

    ChatGPT --> AppStaging

그리고 https://staging.giftgenius.app 내부에는 Next.js, MCP 서버, staging 데이터베이스 등 모든 구성요소가 돌아갈 수 있습니다.

이 강의에서는 Vercel 배포 상세는 다루지 않습니다. 다음 주제의 과제입니다. 지금은 단지 staging이 production과 구성/접근 방식에서 최대한 비슷한 별도의 환경이라는 사실만 받아들이면 충분합니다.

5. Production: 실서버와 실제 사용자

Production 환경은 실제 사용자가 방문하고 실제 돈이 오가는 곳입니다. 여기서는 “main에서 바로 고쳐 보고 결과를 보자” 같은 일은 허용되지 않습니다. 모든 변경은 신중해야 하고, 테스트를 거쳐야 하며 가능하면 롤백 수단을 갖춰야 합니다.

Production 도메인은 안정적이어야 합니다. 무작위 ngrok URL이 아니라 https://giftgenius.app 같은 정식 도메인이어야 하죠. 바로 이 주소를 App 설정에 등록합니다. 사용자가 ChatGPT Store에서 앱을 찾아 실행하면, ChatGPT는 이 엔드포인트를 호출합니다.

Production 환경에는 보통 더 높은 요구 사항이 있습니다:

  • 안정성. 낮은 오류율, 예측 가능한 응답 시간, 부하에서의 정상 동작. 이후 모듈에서 SLO/SLI를 다루겠지만, 직관적으로는 “거의 항상 동작”하고 “거의 항상 빠르게 응답”해야 합니다.
  • 보안. 필요한 비밀만 사용, 최소 권한, PII와 돈을 신중하게 다루기.
  • 실험 제한. 근무 시간 중 “dev 서버 또 재시작” 같은 일 금지. 실험은 피처 플래그, A/B, 별도의 dev/staging 환경으로, 운영 서버 직접 수정으로 하지 않습니다.

ChatGPT 관점에서 production은 Dev Mode가 아닌 공개된 App의 영역입니다. 사용자는 Store나 조직 설정을 통해 접근하고, 검수를 거치며, 모더레이션 앞에서 부끄럽지 않을 만큼 충분히 신뢰할 수 있어야 합니다.

6. Dev Mode vs 프로덕션에서의 App 사용: 무엇이 어디에 연결되는가

가장 흔한 혼동부터 짚고 갑시다. ChatGPT의 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 전용 AppGiftGenius Staging을 따로 만들기도 합니다. 이는 큰 테스트 팀이 있을 때 편리합니다. 본 과정에서는 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 preview URL로 노출됩니다. 이를 위해 별도의 Dev Mode App을 만들거나, 공용 Dev App의 URL을 주기적으로 이쪽으로 바꿔도 됩니다.

main(또는 master) 브랜치는 테스트가 완료된 코드만 담습니다. 이 브랜치가 production URL로 배포되며, Store의 GiftGenius 앱에 연결됩니다.

대략 이렇게 정리할 수 있습니다:

환경 Git 브랜치 URL ChatGPT App
Local dev
feature/*
https://abc123.ngrok.app
GiftGenius Dev (Dev Mode)
Staging
develop / staging
https://staging.gift...
GiftGenius Dev 또는 GiftGenius Staging
Prod
main
https://giftgenius.app
GiftGenius (Store)

app/config/env.tsAPP_ENV를 기억하시나요? 여기의 'local'/'staging'/'production' 값은 표의 “환경” 열과 직접적으로 대응합니다. 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/prod에서 가끔 수 시간의 디버깅을 구해 줍니다.

8. 미니 실습: 자신의 환경 다이어그램 그리기

Vercel과 로그로 넘어가기 전에, 정말 “냅킨에 그리듯” 자신의 환경 다이어그램을 그려 보는 것이 유용합니다. README.md의 mermaid 다이어그램, 화이트보드 스케치, 노트의 그림이어도 좋습니다.

학습용 GiftGenius의 경우 다음과 같이 그릴 수 있습니다:

graph TD
    subgraph ChatGPT
      DevMode["Dev Mode
(당신과 팀)"] Store["Store
(실제 사용자)"] end subgraph Servers Local[Local dev
터널 → localhost] Staging[Staging
staging.giftgenius.app] Prod[Production
giftgenius.app] end DevMode --> Local DevMode --> Staging Store --> Prod

강의 직후에 해 볼 만한 유용한 연습:

  1. 이미 가지고 있는 모든 환경을 적어 보세요. 터널이 달린 로컬, 초기 Vercel 배포 등.
  2. 그 옆에 어떤 Git 브랜치가 어디로 배포되는지 적으세요.
  3. 또 그 옆에 어떤 ChatGPT Apps(또는 커넥터)가 어디를 바라보는지도 적으세요.
  4. ChatGPT가 각 서버로 어떻게 접근하는지 화살표로 표시하세요.

혼자가 아니라면, 리포지토리에 architecture/environments.md 같은 파일을 만들어 두세요. “staging이 다운됐는데 URL이 뭔지 아무도 모른다”는 일을 크게 줄일 수 있습니다.

이를 애플리케이션과 연결하려면, 지금 당장 Dev Mode에서 App 하나(GiftGenius Dev)를 만들고 기본적으로 로컬 환경의 터널을 바라보게 하세요. 그리고 전체 릴리스를 테스트하고 싶을 때만 임시로 staging URL로 바꿉니다. 다음 강의에서 staging/prod를 Vercel에 배포하고 환경 변수와 연결하는 방법을 배웁니다.

모든 내용을 한 문장으로 모으면 이렇습니다. 여러분의 App을 위한 좌표계로 환경과 Dev Mode를 다루세요. 로컬은 빠른 개발용, staging은 최종 리허설, production은 실제 사용자용, 그리고 Dev Mode는 그 사이를 전환하는 스위치이지, 별도의 마법 같은 환경이 아닙니다.

9. 환경과 Dev Mode를 다루면서 흔한 실수

오류 №1: localhost + 터널만으로 운영이라 착각하기.
이 방식은 편해 보일 수 있습니다. “staging과 prod는 굳이 필요 없고, 터널 잘 되고 ChatGPT도 붙는데?” 하지만 터널은 URL이 불안정하고, 네트워크 특성도 다르며, 전체 구성이 한 대의 노트북에 의존합니다. OAuth callback, Stripe webhooks, MCP Gateway 같은 것이 필요해지는 순간, 제대로 된 staging/prod가 없으면 고통을 겪게 됩니다.

오류 №2: Dev Mode를 별도의 환경으로 혼동하기.
“Dev Mode가 있으니 dev 환경도 있는 거네”라고 생각하기 쉽습니다. 실제로 Dev Mode는 ChatGPT에게 “어디로 갈지”만 알려 줍니다. 터널이든 staging이든 심지어 prod든요. 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에서는 안 되고, prod에서는 또 다름” 같은 일이 시작됩니다. 이 간단한 표나 markdown 파일은 그 이상의 가치를 합니다.

오류 №5: local dev와 staging의 차이를 과소평가.
로컬에서는 dev 서버를 띄우고, 키/서비스/네트워크가 하나의 세트로 묶여 있습니다. staging에서는 코드를 빌드하고, 다른 환경에서 다른 제한, 타임아웃, 라우팅 하에서 실행됩니다. 모든 테스트를 로컬에서만 하고 staging을 “형식상” 유지하면, 치명적인 버그가 prod에서 나타납니다. “로컬 → staging 검증 → production 릴리스” 체계를 습관화하세요.

오류 №6: 환경 구성을 무시하고 ChatGPT에게만 문제 해결을 묻기.
문제가 생기면, “무엇이 잘못됐는지 ChatGPT에게 묻기”부터 하는 경우가 있습니다. 대신 그림을 보세요. 어떤 App이 어떤 URL에 연결되어 있고, 어느 환경에서 장애가 발생했으며, 로그는 어디에 있는지 말이죠. 오늘 만든 환경 도식은 다음 강의(로그 확인, MCP 인스펙터 사용, 마지막으로 모델 검토)의 기초가 됩니다.

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION