1. 소개
ChatGPT App을 그저 “또 하나의 웹 서버”로 보기 시작하면 금세 아키텍처가 혼란스러워집니다: 어느 곳엔 Next.js, 또 다른 곳엔 MCP 서버, 또 다른 곳엔 에이전트, 또 다른 곳엔 커머스 백엔드 — 이 모든 것이 머릿속에서 하나의 큰 “서버”로 뭉개지죠.
처음부터 이것이 레이어 케이크라는 사실을 받아들이는 편이 훨씬 유리합니다:
- 맨 위 — 우리가 제어하지는 못하지만 그에 맞춰 적응해야 하는 ChatGPT UI;
- 그 아래 — 채팅에 렌더링되는 Apps SDK(Next.js 16, React 19) 기반의 우리 위젯;
- 그 아래 — 도구(tools/resources/prompts)를 제공하는 MCP 서버;
- 옵션 — 복잡한 시나리오를 오케스트레이션하는 에이전트 레이어;
- 그리고 가장 아래 — 여러분의 “현실” 서비스: DB, 외부 API, commerce/ACP(커머스 시나리오용 프로토콜) 등.
강의 노트에서는 이 경로를 다음과 같은 체인으로 그릴 수 있습니다:
User → ChatGPT Widget → Apps SDK → MCP Gateway (Auth) → Agent Service → ACP / Stripe.
이제 이 체인을 이해하기 쉬운 정신적 모델로 바꾸는 것이 우리의 과제입니다.
2. 스택의 전체 개요
먼저 전체 그림을 보고, 그다음 레이어별로 내려가 봅시다.
flowchart TD
U[ChatGPT의 사용자] --> C["ChatGPT UI 채팅 + Apps 패널"]
C --> W["여러분의 App 위젯 (Apps SDK, Next.js)"]
W --> M["MCP 서버 (tools/resources/prompts)"]
M --> AG["에이전트(들) (Agents SDK, 오케스트레이션)"]
AG --> B["백엔드와 ACP DB, 서비스, 결제"]
몇 가지를 짚고 넘어가야 합니다.
첫째, 사용자는 오직 두 레벨만 봅니다: ChatGPT UI와 여러분의 위젯. 그 아래는 모두 “무대 뒤”입니다.
둘째, MCP 프로토콜은 우연한 약어가 아니라 Apps SDK가 여러분의 도구들과 통신하는 공식 표준입니다. 서버는 tools를 나열하고, call_tool을 수신하고, ChatGPT에서 렌더링할 UI 리소스 링크를 돌려줄 수 있어야 합니다.
셋째, Agents와 ACP 레이어는 형식상 선택 사항이지만 실제 상용 앱에서는 거의 항상 필요해집니다. 어디선가는 다단계 시나리오를 계획해야 하고, 또 어디선가는 결제를 받아야 하죠.
이제 각 레이어를 따로 살펴보겠습니다.
Insight: ChatGPT는 프레임워크다
ChatGPT와의 통합은 한 곳에만 있는 게 아니라 수많은 통합 지점에 고루 퍼져 있습니다. 개발자 입장에서는 프레임워크와 일하는 것과 매우 흡사합니다. 프레임워크가 언제 어디서 여러분의 코드를 호출할지 결정하고, 여러분은 그저 올바른 곳에 올바른 것을 작성하면 됩니다.
ChatGPT에서도 정확히 이렇게 동작합니다:
- 위젯 — mcp-resources로 등록하며, GPT가 언제 표시할지 스스로 결정합니다
- mcp-tools — GPT가 언제 호출할지 스스로 결정합니다
- product feed — mcp-tool로 모델에 추가할 수도 있지만, 표준 방식은 site register merchant 를 통해서입니다
- ACP/InstantCheckout — 별도의 API
- 인증 — 별도의 mcp auth 서버.
3. 레이어 1 — ChatGPT UI: 우리의 ‘호스트’
ChatGPT UI는 사용자가 핵심 대화를 나누는 OpenAI의 브라우저(및 모바일) 인터페이스입니다. 익숙한 입력창, 메시지 히스토리, 모델 선택 버튼, 앱 탭(Store/Composer)이 여기에 있습니다.
이 레이어는 우리가 프로그래밍하지 않습니다. 코드, DOM, 스타일에 접근 권한이 없습니다. 하지만 이 레이어가 기준을 정합니다:
- 사용자가 명시적으로(Store/Composer) 또는 암묵적으로(모델이 App을 제안) 여러분의 앱을 “선택”하는 곳이 바로 여기이며;
- 텍스트로 답할지, 여러분의 tool을 호출할지, 위젯을 렌더링할지, 혹은 이 모든 것을 동시에 할지를 ChatGPT가 여기서 결정하며;
- 기본 UX 패턴(인라인 위젯, 전체 화면, PiP 창 등)이 이곳에 존재합니다(자세한 내용은 모듈 8).
실용적인 관점에서 기억할 점: ChatGPT UI는 우리의 호스트 애플리케이션입니다. 우리는 그 안에 임베드됩니다. GPT 서버는 여러분의 위젯 코드를 자신의 서버로 가져와 불필요한 것을 정리한 뒤, 자신의 도메인에서 채팅에 로드합니다.
4. 레이어 2 — Apps SDK와 위젯(채팅 내부의 Next.js 16)
다음 레이어는 Apps SDK를 사용해 React/Next.js로 작성한 여러분의 UI 코드입니다.
정신적 모델은 간단합니다: 채팅에 임베드되는 위젯으로 렌더링되는 미니 SPA와 같습니다. 다만 주의할 점이 있습니다:
- 여러분의 코드는 샌드박스에서 동작합니다: 제한된 DOM, 특별한 네트워크 규칙, 그리고 ChatGPT와 연결하기 위한 특수 객체 window.openai 가 있습니다(별도 강의에서 다룹니다).
- 위젯은 대화 흐름을 제어하지 않습니다: 사용자는 전체 채팅에 입력하고, 모델이 언제 여러분의 App을 부를지 결정하며, 여러분은 자신의 “프레임” 안에서만 응답합니다.
- Apps SDK가 모든 것을 처리합니다: 위젯 상태를 대화 히스토리와 동기화하고, tool 결과를 처리하며, MCP와 상호작용합니다.
Next.js 개발자 관점에서는 익숙하게 보일 것입니다: 페이지/컴포넌트, 훅, 프롭스가 있습니다. 하지만 고전적인 fetch('/api/...') 대신 MCP 서버에 정의된 도구(tools)와 Apps SDK의 특수 훅을 더 자주 의존하게 됩니다(자세한 내용은 이후 강의에서).
조금 더 구체화해 보죠. 우리의 예시 프로젝트 — 가칭 GiftGenius를 떠올려 봅시다. 이 App은 “누구에게, 얼마 예산으로, 어떤 기념인지” 등 파라미터로 선물을 추천합니다.
앞으로 만들 UI의 작은 조각(아직 SDK 특수 기능은 제외, 아이디어 수준):
// GiftSummary.tsx — 우리 App의 간단한 React 컴포넌트
type GiftIdea = {
id: string;
title: string;
price: number;
};
interface GiftSummaryProps {
ideas: GiftIdea[];
}
export function GiftSummary({ ideas }: GiftSummaryProps) {
return (
<ul>
{ideas.map((idea) => (
<li key={idea.id}>
{idea.title} — ${idea.price}
</li>
))}
</ul>
);
}
나중에 이 컴포넌트는 MCP 서버의 도구 결과(ToolOutput)에서 ideas를 받게 됩니다. 하지만 아키텍처 관점에서 더 중요한 건, 이런 코드는 모두 “두 번째 레이어”에 살며 상태 표시만 담당한다는 점입니다.
5. 레이어 3 — MCP 서버: 도구와 데이터의 세계
이제 서버 쪽으로 내려가 봅시다.
Model Context Protocol (MCP)은 LLM 클라이언트(ChatGPT, Apps SDK, Agents)가 여러분의 서버와 어떻게 통신하는지를 기술하는 표준입니다. 어떤 도구가 있고, 그 input/output 스키마는 무엇이며, 어떻게 호출하고, 어떤 리소스/프롬프트를 로드할 수 있는지를 규정합니다.
Apps SDK를 위한 최소한의 MCP 서버는 세 가지를 할 수 있어야 합니다:
- 도구 목록(List tools)을 JSON Schema와 메타데이터와 함께 반환;
- 도구 호출(Call tools)을 처리 — call_tool 요청을 수신해 비즈니스 로직을 실행하고 구조화된 결과를 반환;
- html, js, css, ... 반환 — 도구가 특정 위젯 표시와 연결된 경우 선택적으로 해당 UI 리소스를 제공합니다.
중요한 점: MCP는 전송 방식에 독립적인 프로토콜입니다. ChatGPT Apps에서는 HTTP 변형과 스트리밍 가능한 구현이 중요하지만, 전송과 메시지 포맷의 세부사항은 MCP 모듈(레벨 6)의 주제입니다. 지금은 Apps SDK가 “아래쪽”으로 임의의 REST 엔드포인트가 아니라 MCP 서버로 통신한다는 점만 이해하면 충분합니다.
아키텍처적으로 MCP 레이어는 자주 별도 마이크로서비스처럼 보입니다:
flowchart LR
subgraph App["여러분의 ChatGPT App"]
W["위젯 (Next.js + Apps SDK)"]
M["MCP 서버 (@modelcontextprotocol/sdk)"]
end
W <-- JSON-RPC over HTTP/SSE --> M
M --> DB[(선물 카탈로그)]
M --> EXT[외부 API]
MCP 서버 내부에서는 평범한 TypeScript/Node 코드를 작성하고, 데이터베이스, 큐, 서드파티 API 등을 사용할 수 있습니다. MCP를 위한 공식 TypeScript SDK가 JSON-RPC 직렬화, 스키마 검증, 호출 라우팅을 담당합니다.
우리 GiftGenius의 MCP 도구 중 하나는 search_gifts라고 부를 수 있습니다. TypeScript 수준에서는 평범한 함수처럼 보일 수 있습니다:
// 의사 코드: MCP 서버 내부의 비즈니스 로직
export async function searchGifts(params: {
recipient: string;
budget: number;
}) {
// 여기서부터는 DB/카탈로그를 조회합니다
const items = await findGiftsInCatalog(params);
return items.slice(0, 10);
}
나중에 이를 MCP tool로 감싸고 스키마를 기술하겠지만, 핵심은 이 레이어가 MCP를 통해 세상과 대화하는 여러분의 “정상적인” 백엔드라는 점입니다.
6. 레이어 4 — Agents SDK: 복잡한 시나리오의 두뇌
모든 앱에 에이전트가 필요한 것은 아니지만, 시나리오가 “하나의 도구 호출 → 하나의 응답”을 넘어서는 순간 에이전트 레이어는 매우 유용해집니다.
에이전트는 본질적으로 제어 가능한 LLM 프로세스로서:
- 사용자 요청과 대화 히스토리의 사실을 읽고;
- 어떤 도구를 어떤 순서로 어떤 인자로 호출할지 단계(sequence)를 계획하며;
- 결과를 분석하고 “도구 재호출”, “사용자에게 추가 질문”, “더 복잡한 응답 구성” 같은 결정을 내리며;
- 때로는 단계 사이의 상태(메모리, 세션, 체크포인트 등)를 저장합니다(이는 레벨 12의 주제).
Agents SDK는 이러한 시나리오를 구조적으로 기술할 수 있는 방법을 제공합니다: 에이전트가 사용할 수 있는 도구, 상태의 저장/복구, 루프 제한 등. 에이전트는 백엔드 내부에서 실행되며, ChatGPT Apps 위젯의 제약 없이 OpenAI의 능력을 여러분이 원하는 방식으로 활용할 수 있게 해줍니다.
우리 스택의 맥락에서 에이전트는 보통 MCP 레이어와 도메인 API 사이의 백엔드에 위치합니다. 외부 API, 내부 함수, MCP 도구를 “손”처럼 사용하고, 자신은 “머리” 역할을 합니다.
예를 들어 GiftGenius의 시나리오는 다음과 같습니다:
- 사용자가 “엄마에게 줄 50달러 이하 선물을 골라줘”라고 작성합니다.
- ChatGPT가 여러분 앱의 search_gifts 도구를 호출합니다.
- search_gifts 도구 뒤에서는 서버의 에이전트가 먼저 몇 가지 세부사항(관심사, 용도)을 묻기로 결정할 수 있습니다.
- 사용자가 추가 요구 사항을 자세히 적습니다.
- ChatGPT가 추가 인자를 포함해 여러분 앱의 search_gifts 도구를 다시 호출합니다.
- 서버의 에이전트는(예: 재고 확인 같은) 추가 도구를 호출할 수 있습니다.
- ChatGPT에 준비된 후보들과, 필요하다면 시각화를 위한 위젯 링크를 반환합니다.
강의 후반부에서 에이전트의 run 사이클, 멱등성, 보안을 자세히 다루겠지만, 전체 아키텍처 관점에서 중요한 점은: 에이전트 레이어는 선택 사항이지만 복잡한 오케스트레이션을 덜어주는 매우 강력한 “두뇌”라는 것입니다.
7. 레이어 5 — ACP/백엔드: 결제, 데이터, 그리고 현실의 과제들
가장 아래 레이어는 여러분의 일반적인 서비스입니다:
- 데이터베이스(상품 카탈로그, 사용자, 주문);
- 외부 API(결제 제공자, 물류, 서드파티 SaaS);
- ACP(Agentic Commerce Protocol)와 Instant Checkout 같은 특수 프로토콜.
ACP는 ChatGPT와 에이전트가 여러분의 커머스 백엔드와 어떻게 상호작용하는지(상품 SKU 탐색, 장바구니 생성, 주문 처리, 환불, 성공/실패 웹훅 등)를 정의합니다.
GiftGenius의 경우 대략 다음과 같습니다:
- MCP 도구 search_gifts가 제품 피드/DB에서 읽습니다;
- 에이전트가 특정 상품을 선택하면 commerce 인텐트(ACP)를 시작합니다;
- ACP 호환 백엔드가 PaymentService에 “결제 진행”을 지시하고, 상태를 ChatGPT에 알립니다;
- 사용자는 외부 사이트로 이동하지 않아도 ChatGPT에서 주문 완료 상태를 확인합니다.
이제 레이어를 훑어봤으니, 구체적인 end-to-end 시나리오를 살펴봅시다.
8. 엔드투엔드 시나리오: 사용자의 요청이 모든 레이어를 통과하는 방법
다음 요청을 예로 들어봅시다: “엄마에게 줄 50달러 이하의 선물을 골라줘. 독서와 차를 좋아해.”
단계를 나눠 보겠습니다.
- 사용자가 ChatGPT에 텍스트를 입력합니다. 이것이 첫 번째 레이어 — ChatGPT UI입니다. 사용자에게는 평범한 채팅처럼 보입니다.
- 모델이 대화 히스토리, 여러분 App의 메타데이터(설명, 카테고리, 권한)를 읽고 GiftGenius가 적절한 후보라고 판단합니다. Apps SDK의 디스커버리 규칙에 따르면, 모델은 도구 설명 텍스트, 과거 사용 경험, 컨텍스트, 심지어 브랜드 언급까지 고려합니다.
- ChatGPT는 다음 중 하나를 수행합니다:
- UI 없이 바로 여러분 App의 도구를 호출(tool-first 시나리오);
- 또는 응답으로 “GiftGenius를 사용해서 선물 선택을 도와줄 수 있어요”라고 제안하고 도구를 호출.
- ChatGPT가 도구 search_gifts에 대해 MCP 서버로 call_tool 요청을 보냅니다. MCP 서버는 비즈니스 로직을 수행합니다: DB/피드로 조회하고, 예산과 선호도를 기준으로 필터링한 뒤, 적합한 상품 목록(JSON)을 반환합니다.
- 도구 결과가 ChatGPT로 돌아옵니다. 모델은 다음을 할 수 있습니다:
- 그 결과를 텍스트 응답(“다음은 선물 아이디어 3가지입니다…”)의 데이터로만 사용하고 위젯은 보여주지 않거나;
- 도구 결과를 위젯에 전달해 카드형 UI로 시각화하도록 위젯을 표시합니다.
- 이 시점에서 비로소 여러분의 GiftGenius 위젯(Apps SDK)이 실행되고, Next.js 코드가 채팅 내부에 렌더링됩니다. 위젯은 예를 들어 “누구에게?”, “예산”, “관심사” 같은 추가 입력 폼을 보여줄 수 있습니다. 사용자는 버튼을 클릭하거나 계속 채팅에 입력할 수 있으며, 모델이 이를 App과 동기화합니다.
- 위젯이 실제 데이터(선물 카탈로그)를 필요로 하면, fetch('https://my-backend/gifts') 를 직접 호출하지 않습니다. 대신 MCP 도구 호출을 스스로 트리거합니다: ChatGPT가 다시 MCP 서버로 도구 search_gifts에 대한 call_tool 요청을 보냅니다.
- 시나리오가 다단계(추가 질의, 랭킹, 재고 추가 확인, 대안 제안 등)라면, 에이전트 레이어가 계획, 워크플로 관리, 에이전트 오케스트레이션을 담당합니다.
- 사용자가 특정 상품을 “구매”하기로 하면 ChatGPT가 ACP 프로토콜로 구매를 시작합니다. 커머스 백엔드는 ACP와 Instant Checkout으로 결제를 처리하고 상태를 응답하며, 웹훅을 트리거합니다. ChatGPT는 사용자에게 최종 상태(“주문 완료, 영수증은 여기”)를 보여줍니다.
개발자 관점에서 각 레벨의 책임 범위가 명확하다는 점이 장점입니다. 그리고 모든 레이어가 새로운 표준화 프로토콜(MCP, ACP)로 연결되어 있다는 점도 중요합니다. 낡은 REST 요청만으로 연결하는 시대가 아닙니다.
이 모든 것은 논리적 그림입니다: 어떤 레이어가 존재하며, 요청이 그 레이어를 어떻게 흐르는지. 이제는 물리적 측면으로 넘어가겠습니다. 이 레이어들이 코드와 인프라에서 정확히 어떻게 배치되는지 — 하나의 Next 모놀리식으로 갈지, 여러 서비스로 나눌지(여기서 말하는 것은 모놀리식 vs 마이크로서비스의 일반론이 아닙니다).
9. Next.js 모놀리식 vs 분리된 아키텍처
이제 자연스러운 질문: “이 모든 것이 반드시 여러 개의 별도 서비스여야 하나요? 그냥 하나의 Next.js 모놀리식으로 만들면 안 되나요?”
답: 가능합니다. 강의는 단순한 것부터 복잡한 것으로 진행합니다. 초기에는 “거의 모든 것”을 한 저장소, 심지어 하나의 런타임에 모아도 충분히 괜찮습니다:
flowchart LR
U[ChatGPT] --> W["Next.js App (Apps SDK)"]
W --> M["MCP endpoint (같은 Next.js 내)"]
M --> DB[(DB/카탈로그)]
즉, 여러분의 Next.js 서버(API 라우트 또는 별도 서버)가 동시에 다음을 수행합니다:
- UI 위젯 제공(Apps SDK 페이지/컴포넌트),
- MCP 엔드포인트 구현(HTTP 위의 JSON-RPC),
- DB/외부 API 호출.
이는 개발 모드와 초기 버전의 App에 편리합니다: 움직이는 부분이 적고, 배포가 더 단순합니다.
그러나 기능이 커질수록 레이어를 분리할 이유가 생깁니다:
- MCP 서버는 별도로 스케일링해야 할 수 있습니다(무거운 도구가 많음);
- 재무/결제 백엔드는 자체 도메인에서 운영되고, 다른 팀이 관리하며, 별도의 보안 요구가 있습니다;
- 에이전트 로직은 자체 모니터링과 SLA를 가진 별도 애플리케이션으로 분리될 수 있습니다.
그렇게 되면 그림은 다음과 같이 바뀝니다:
flowchart TD
U[ChatGPT] --> W[Next.js + Apps SDK]
W --> MG[MCP Gateway]
MG --> M1[MCP Gifts Server]
MG --> M2[MCP Analytics Server]
M1 --> AG[Agent Service]
AG --> ACP[Commerce/ACP Backend]
MCP Gateway라는 개념이 추가됩니다 — ChatGPT를 위한 공용 진입점입니다. 다양한 MCP 서버로 라우팅하고, REST API와 통합하며, 인증, 요청 제한(rate limiting) 등을 관리합니다.
우리는 더 모놀리식한 시나리오부터 예제를 작성하겠지만, 처음부터 코드를 나중에 무리 없이 분리할 수 있도록 구성할 것입니다.
10. 정확히 어디에 코드를 작성하고(그리고 무엇을 다른 곳에 위임하는지)
레이어를 모놀리식 또는 분산 아키텍처로 조합할 수 있다고 짚었으니, 정확히 어디에서 여러분이 코드를 작성하고, 무엇을 다른 서비스/팀에 위임할지 명확히 해두는 것이 좋습니다.
TypeScript/Next.js 개발자 관점에서 여러분이 통제하는 구역을 분명히 표시해 봅시다.
위젯(Apps SDK + Next.js)에서 여러분은:
- 도구 상태와 사용자 입력을 표시하는 React 컴포넌트를 작성합니다;
- Apps SDK 훅을 사용해 ToolInput/ToolOutput과 위젯 상태(widget state)를 읽습니다;
- 표시 모드(인라인/전체 화면/PiP), 테마, 크기 등을 설정합니다(레벨 8에서 다룸);
- 고급 시나리오를 위해 window.openai 를 통해 ChatGPT와 상호작용합니다(강의의 별도 모듈).
MCP 서버에서 여러분은:
- MCP SDK로 tools/resources/prompts를 기술합니다;
- 도구의 비즈니스 로직을 구현합니다(본질적으로 DB, API 등을 호출하는 평범한 TypeScript 함수);
- 모델이 읽기 쉽도록 스키마와 응답을 최적화합니다(환각을 줄이고 구조화를 높임).
에이전트 레이어(Agents SDK를 사용하는 경우)에서 여러분은:
- 에이전트가 사용할 수 있는 도구와 목표를 기술합니다;
- run 사이클, 메모리, 루프 제어를 설정합니다;
- 에이전트가 엉뚱한 일을 하거나 무한 계획에 빠지지 않도록 관리합니다.
ACP/백엔드에서 여러분은:
- 기존 커머스 서비스(Stripe, 자체 스토어의 product feed 등)와 통합하거나;
- ACP를 이해하고 주문을 처리/반환할 수 있는 새로운 백엔드를 설계합니다.
중요: 성숙한 제품에서는 한 사람이 모든 레이어를 완전히 소유하는 경우가 드뭅니다. 하지만 프로토타입 단계(그리고 이 강의에서는) 최소한 어떤 위치에 어떤 코드가 있는지 이해할 수 있기를 기대합니다.
11. 아키텍처가 UX와 플랫폼 정책에 미치는 영향
UX와 정책은 별도 모듈의 주제이지만, 이미 아키텍처 단계에서 선택한 레이어 분리가 UX와 플랫폼 요구 사항에 어떤 영향을 주는지 이해하는 것이 중요합니다. 미리 몇 가지를 짚고 가겠습니다.
첫째, 샌드박스. 위젯은 무분별하게 인터넷을 탐색하거나 사용자 데이터를 수집할 수 없습니다 — 모든 것은 통제된 도구와 MCP/Store에 기술된 권한을 통해 이뤄집니다. 플랫폼은 여러분이 App에 필요한 데이터와 동작을 정직하게 기술하기를 기대하며, 이 설명을 바탕으로 App 디스커버리/추천을 수행합니다.
둘째, UX 흐름. 모델이 일시적으로 여러분의 App을 “잊어버리거나”, 반대로 지나치게 공격적으로 제안할 수 있기 때문에, 아키텍처는 중단에 친화적이어야 합니다: 에이전트가 긴 워크플로를 마치지 못했는데 사용자가 주제를 바꾸더라도 앱은 이를 문제없이 처리해야 합니다. 강의에서의 다단계 시나리오와 워크플로 오케스트레이션은 MCP 도구와 에이전트 레이어 위에 구축됩니다.
셋째, 판매. App이 결제를 받기 시작하면 추가 보안, 로깅, ACP 계약 등의 요구가 적용됩니다. 여러분이 레이어(UI, MCP, Agents, ACP/Backend)를 어떻게 분리했는지는 Store 리뷰와 보안 감사를 얼마나 수월하게 통과할지에 큰 영향을 줍니다.
첫 정리
여러분의 머릿속에 다음과 같은 개요 지도가 그려졌기를 바랍니다:
- 상단 레이어(ChatGPT UI + Apps SDK)가 사용자가 여러분의 App을 어떻게 보고 느끼는지를 결정합니다;
- 중간 레이어(MCP)는 모델에 도구와 데이터를 제공하는 표준 방식입니다;
- 에이전트와 커머스 레이어가 여러분의 App을 단순한 “데이터 뷰어”가 아닌 논리와 결제를 갖춘 완전한 제품으로 만듭니다.
두 번째 레벨에서는 가장 흥미로운 것부터 시작합니다: Next.js 기반의 공식 Apps SDK 템플릿을 내려받아 로컬에서 실행하고 Dev Mode의 ChatGPT에 연결합니다. 즉, 우선 Apps SDK/위젯 레이어를 직접 만져보고, MCP/에이전트는 당분간 스텁이거나 내장 백엔드로 두겠습니다.
하지만 지금부터도 현재의 스키마를 머릿속에 유지하는 것이 중요합니다: 마치 모노레포를 볼 때 apps/ — 는 UI, services/mcp — 는 프로토콜, services/agent — 는 오케스트레이터, 그리고 services/commerce — 는 결제/커머스라는 것을 이해하는 것처럼요.
12. 스택 아키텍처를 오해할 때의 전형적인 실수
오류 №1: ChatGPT App = 그저 “내 REST API로의 웹훅”이라고 생각하기.
“봇” 세계의 습관으로 이렇게 만들 수도 있습니다: 모델이 그냥 내 URL로 POST 요청을 보내고, 그다음은 알아서 처리하면 된다고요. 실제로는 모델과 여러분의 코드 사이에 Apps SDK와 MCP가 있습니다. 임의의 HTTP 요청을 “청취”하는 게 아니라, 도구, 그 스키마, 동작을 기술해야 합니다.
오류 №2: UI와 비즈니스 로직 레이어를 뒤섞기.
흔한 안티 패턴은 복잡한 도메인 로직을 위젯에 끌어올리고, MCP 레이어를 얇은 중계로 만드는 것입니다. 그렇게 되면 UI가 무거워지고, 테스트하기 어렵고, ChatGPT 밖에서 재사용하기도 좋지 않습니다. 규칙과 데이터 접근은 MCP/에이전트 레벨에 두고, 위젯은 표시와 단순 인터랙션에 집중하는 편이 훨씬 견고합니다.
오류 №3: MCP를 무시하고 “자체 프로토콜”을 작성하기.
때로는 “MCP가 왜 필요해? 그냥 JSON을 반환하면 모델이 알아서 처리하겠지”라는 유혹이 생깁니다. 짧은 데모에서는 “되는 것처럼” 보일 수도 있지만, 그 순간 MCP와 Apps SDK가 제공하는 표준 기능(디스커버리, 인스펙션, 인증, 멀티클라이언트 지원)을 잃게 됩니다.
오류 №4: App 전체를 한 레이어 주도로 구성하기.
누군가는 모든 것을 “에이전트” 안에 넣어 과도한 책임을 지우고, 누군가는 반대로 모든 것을 MCP 도구에 욱여넣고, 누군가는 거대한 Next.js 모놀리식을 만듭니다. 올바른 접근은 각 레이어의 책임을 인정하는 것입니다: UI — 표시, MCP — 데이터/행동 접근, 에이전트 — 오케스트레이션, ACP/백엔드 — 도메인 불변성과 결제.
오류 №5: 아키텍처가 Store 리뷰와 보안에 미치는 영향을 과소평가하기.
MCP 엔드포인트이자 ACP 리소스이자 시크릿을 보관하고 로그에 모든 것을 그대로 기록하는 “단일 서버”로 운영한다면, 보안/콘텐츠 정책 리뷰가 길어질 수 있습니다. 명확한 경계와 프로토콜을 가진 분리된 아키텍처는 후반 단계에서 삶을 훨씬 편하게 해줍니다.
GO TO FULL VERSION