1. Multi‑App 시나리오는 무엇이며 왜 필요한가
지금까지 우리는 GiftGenius를 특정 채팅에서 단 하나의 외부 애플리케이션으로만 보았습니다. 사용자가 목록에서 여러분의 App을 선택하면 ChatGPT가 여러분의 tools를 올리고, 여러분이 이야기의 “주인공”이 됩니다. 실제 Store에서는 다릅니다. 사용자는 여러 App을 동시에 연결할 수 있고, ChatGPT는 특정 요청에 대해 어떤 애플리케이션을 호출할지 결정합니다.
예를 들어, 한 채팅에는 다음과 같은 App이 함께 있을 수 있습니다:
- 동료의 생일을 알고 있는 기업용 캘린더 App;
- 선물 아이디어를 추천하는 GiftGenius;
- 주문과 결제를 처리할 수 있는 회사의 commerce‑App.
사용자가 이렇게 씁니다: “동료들 생일을 잊지 않게 해주고, 바로 무엇을 선물할지 추천하고 어떻게 살지도 제안해줘.” 모델은 순차적으로 서로 다른 세 개의 App을 호출할 수 있습니다. 하나는 캘린더, 둘째는 선물 아이디어, 셋째는 체크아웃을 맡습니다.
중요한 점: 사용자에게 “App 2번을 호출해 주고, 이것이 그의 HTTP‑endpoint야” 같은 버튼은 없습니다. 사용자는 자연어로 대화하고, ChatGPT는 라우터 역할을 하며 — 모든 사용 가능한 애플리케이션의 descriptions와 메타데이터를 읽고 언제 누구를 호출할지 결정합니다.
여기에서 세 가지 핵심 포인트가 나옵니다:
- 컨텍스트 경쟁이 일어납니다. 여러분의 App은 이름, 설명, 동작을 바탕으로 수십 개 중에서 선택되어야 합니다.
- 메타데이터는 여러분의 “LLM을 위한 SEO”가 됩니다 — 메타데이터가 모델이 적절한 순간에 GiftGenius를 떠올릴지, 아니면 무시할지를 좌우합니다.
- 상호운용성을 고려해야 합니다: 여러분의 응답은 채팅의 사람뿐 아니라 같은 컨텍스트를 읽는 다른 App에게도 유용해야 합니다.
본질적으로, 우리는 격리된 ChatGPT App을 더 큰 시스템의 구성 요소로 바꾸는 것입니다.
2. 모델은 App을 어떻게 고르는가: 라우팅에 대한 멘탈 모델
Multi‑App 시나리오에서 라우팅은 대략 다음과 같이 이뤄집니다(매우 단순화했지만 개발에 유용한 수준):
- ChatGPT에는 사용 가능한 App과 그 tools, 그리고 메타데이터(이름, 설명, JSON 스키마 파라미터, 애너테이션, _meta) 목록이 있습니다.
- 사용자가 메시지를 작성합니다.
- 모델은 의도(intent)의 내부 표현을 만들고, 사실상 descriptions (tools 및 앱)로 의미 기반 검색을 하여 어떤 도구가 적절한지 파악합니다.
- 조건이 맞으면 tool을 호출하거나 App 열기를 제안합니다.
여기서 중요한 뉘앙스가 있습니다. descriptions는 충분히 구분 가능해야 합니다. “상품 검색”이라는 표현은 “선물 검색”, “책 검색”과 크게 다르지 않습니다. 하지만 “GiftGenius 파트너 데이터베이스를 사용해 선물 아이디어 검색”은 도메인을 크게 좁혀 선물 관련 요청에서 여러분의 도구가 선택될 확률을 높입니다.
두 번째 포인트 — 이름 충돌을 피하세요. get_data 같은 이름의 도구는 수십 개 App의 세계에서 아무 의미가 없습니다. 반면 giftgenius_get_gift_catalog는 훨씬 명확합니다. 특히 또렷한 description과 결합되면 더욱 그렇습니다.
마지막으로, 모델은 컨텍스트에 의존합니다. 채팅에서 이미 “선물”, “생일”, 나아가 GiftGenius라는 이름이 언급되었다면, 라우터의 눈에 여러분의 App이 더 강조됩니다.
3. 메타데이터와 descriptions를 LLM‑SEO로
메타데이터를 “JSON에 들어가는 의무적인 형식”으로만 여기지 말고, 제품 카피라이팅 작업으로 생각하는 것이 유익합니다. 공식 권장 사항은 명확합니다. treat metadata like product copy, 그리고 “one job per tool”로 설계하세요.
설명에는 대략 다음과 같은 몇 가지 수준이 있습니다:
| 수준 | 대상 | 무엇을 설명하나 |
|---|---|---|
| Manifest description | 사람 + 모델 | App 전체의 과업: 왜 채팅에 포함해야 하는가 |
| Tool description | 모델(라우팅) | 특정 tool을 언제, 어떤 작업에 사용할지 |
| Parameter descriptions | 모델(slot fill) | 인자를 어떻게 채우고 어떤 값이 허용되는지 |
|
모델(UI) | 위젯에 정확히 무엇이 나타나는지, 그리고 모델이 텍스트 답변으로 이를 중복해야 하는지 |
widgetDescription는 위젯 환경에서 특히 중요합니다. 모델은 여러분의 React 코드를 “보지” 못하고, 여러분이 어떤 props를 왜 넘길지를 알 뿐입니다. 이 필드를 잘 채우면 모델이 임의로 지어내지 않고, 이미 표시된 UI를 고려하여 텍스트 답변을 조정할 수 있습니다.
Apps SDK 문서는 다음을 강조합니다. ChatGPT는 메타데이터를 바탕으로 여러분의 커넥터(App)를 언제, 어떻게 호출할지 결정합니다. 정교한 descriptions와 파라미터 문서는 recall — 즉 모델이 여러분의 App을 떠올리는 상황의 비율 — 을 높이고, 오작동을 줄여 줍니다.
미니 예시: GiftGenius의 이전 vs 새로운 description
이전에 다음과 같은 내용이 있었다고 가정해 봅시다:
export const appDescription = `
GiftGenius — 선물 검색과 구매를 돕는 도우미.
`;
사람의 관점에서는 나쁘지 않지만, Multi‑App 세계의 라우팅을 위해서는 App을 언제 사용해야 하는지와 하지 않는 일을 강조하는 편이 좋습니다:
export const appDescription = `
GiftGenius — 선물 아이디어 어시스턴트.
사용자는 특정 사람이나 상황(기념일 등)을 위한 선물을 예산 내에서 고민할 때 이 앱을 사용하세요.
일반적인 온라인 쇼핑이나 개인 재무 계획에는 사용하지 마세요.
`;
이제 모델은 GiftGenius를 일반 e‑commerce App이나 재무 상담가와 쉽게 구분할 수 있습니다.
4. _meta["openai/widgetDescription"]: 모델에게 UI 설명하기
위의 표에서 _meta["openai/widgetDescription"]를 따로 언급했습니다. 이제 여기에 집중해 봅시다. 이 레벨은 모델이 여러분의 위젯을 “상상”하고, 응답의 어느 부분이 이미 UI로 커버되었는지, 무엇을 텍스트로 말해야 하는지를 이해하도록 돕습니다.
예를 들어, 우리의 기본 도구 suggest_gifts가 선물 목록을 반환하고, 위젯은 이를 가로형 카드 캐러셀로 렌더링한다고 가정합시다. 도구의 설명에서는 이미 언제 사용해야 하는지 설명했고, widgetDescription에서는 결과가 어떻게 보이는지를 설명합니다.
도구 디스크립터의 일부(권장사항을 바탕으로 단순화):
const suggestGiftsTool = {
name: "suggest_gifts",
description: "Use this to generate gift ideas within user's budget.",
inputSchema: { /* ... */ },
_meta: {
"openai/widgetDescription":
"가격과 '구매' 버튼이 있는 선물 카드의 가로 목록을 표시합니다. 텍스트 답변에서 선물 이름을 반복하지 마세요."
}
};
여기서 한 번에 여러 목표를 달성합니다:
- 모델은 UI가 이미 이름과 가격을 보여 준다는 것을 알게 되므로, 텍스트 응답에서는 리스트를 중복하지 않고 설명과 조언에 집중할 수 있습니다.
- 다른 App들(모델을 통해서)은 toolOutput이 단순한 텍스트 단락이 아니라 자신들의 컨텍스트에 “이어받을” 수 있는 구조화된 리스트라는 것을 이해합니다.
솔직히 말해 이런 설명을 쓰는 일은 코딩보다 재미없지만, 이런 설명이 나중에 모델의 이상한 행동을 디버깅하는 시간을 크게 줄여 줍니다.
5. 도구 애너테이션: readOnlyHint, destructiveHint, openWorldHint
Multi‑App 세계에서는 “언제 호출할지”뿐 아니라 특정 도구를 호출하는 것이 얼마나 안전한지도 중요합니다. 이를 위해 Apps SDK는 도구 디스크립터에 여러 애너테이션을 도입합니다.
아이디어는 이렇습니다. 애너테이션은 작업 특성에 대한 모델용 완곡한 힌트입니다. 서버 측 인증을 대체하지는 않지만, ChatGPT가 체인에서 어떻게 행동할지에 큰 영향을 줍니다.
짧은 요약(개념적으로):
| 애너테이션 | 의미 | 모델의 전형적 동작 |
|---|---|---|
|
데이터를 변경하지 않음 | 자주, 별다른 확인 없이 호출 가능 |
|
상태를 변경함(구매, 삭제 등) | 호출 전에 사용자에게 확인 요청 |
|
“외부 세계”(검색, 웹)로 나감 | 결과의 범위와 품질에 더 신중 |
애너테이션(readOnlyHint, destructiveHint, openWorldHint)은 도구 표준 설명의 일부이며 ChatGPT 이외에서도 사용할 수 있습니다. _meta["openai/isConsequential"] 필드는 ChatGPT에 특화된 보다 좁은 신호로, 모델이 “안전한 호출”과 “결과를 동반하는 호출”을 더 잘 구분하도록 돕습니다.
GiftGenius의 두 가지 도구를 살펴봅시다:
- suggest_gifts — 카탈로그 읽기, 안전.
- create_checkout_session — 체크아웃 생성, 명백한 side‑effect 작업.
suggest_gifts 도구 설명 예시
const suggestGiftsTool = {
name: "suggest_gifts",
description:
"Use this when the user asks for gift ideas for a person or occasion.",
inputSchema: { /* ... */ },
annotations: {
readOnlyHint: true
},
_meta: {
"openai/widgetDescription": "가격과 링크가 있는 선물 캐러셀.",
"openai/isConsequential": false
}
};
이런 도구는 모델이 연속해서 여러 번, 심지어 “사전적으로” 호출해도 괜찮습니다. 사용자에게 매번 묻지 않고도 미리 후보를 준비할 수 있습니다.
create_checkout_session 도구 설명 예시
const createCheckoutTool = {
name: "create_checkout_session",
description:
"Finalize purchase of selected gifts via Instant Checkout.",
inputSchema: { /* ... */ },
annotations: {
destructiveHint: true
},
_meta: {
"openai/isConsequential": true
}
};
여기서는 명확히 신호를 보냅니다. 이것은 쓰기 작업이며 결과(결제, 주문 생성)가 따르므로, 특히 여러 App이 얽힌 긴 체인에서는 모델이 호출 전에 사용자 확인을 받아야 합니다.
여기서 마법을 과대평가하지 마세요. destructiveHint가 있어도, 보안과 인증에 관한 모듈에서 논의했듯이 서버에서 입력 데이터, 토큰, 권한을 다시 확인해야 합니다. 하지만 Multi‑App 오케스트레이션 관점에서 애너테이션은 모델이 이런 도구를 불필요하게 “난사”하지 않도록 돕습니다.
6. 고립된 App vs 생태계: GiftGenius의 경계를 명확히
GiftGenius가 채팅의 유일한 App이었을 때는 범위를 꽤 넓게 가져가도 괜찮았습니다. 선물 추천, 포장 조언, 기념일 알림, 축하 메시지 짧은 문구까지도요. 모델은 어차피 여러분의 도구만 호출하니까요.
하지만 Multi‑App 시나리오에서는 이런 “다 해요” 접근이 해가 되기 시작합니다:
- 라우터가 여러분이 완벽한 후보일 때와 다른 App을 쓰는 게 나을 때를 구분하기 어려워집니다.
- 캘린더, 범용 작업 관리자, 재무 플래너 등과 영역이 겹치기 시작합니다.
- 여러 앱을 함께 사용할 때 모델이 “엉뚱한” 실행자를 선택하고 도구 사용에서 혼동할 수 있습니다.
더 나은 접근은 책임 범위를 분명히 그리는 것입니다:
- GiftGenius: 선물 아이디어에 한정 + ACP/Checkout을 통한 구매 지원;
- CalendarApp: 이벤트와 리마인더;
- Finance‑App: 사용자의 전체 예산, 개인 재무 계획.
App과 도구 설명에서 “Use this when…”뿐 아니라 “Do not use when…”도 명시적으로 적는 것이 유익합니다. 공식 discovery‑playbook에서도 이를 권장합니다.
도구 설명 미니 예시:
description: `
Use this tool when the user explicitly asks for gift suggestions.
Do not use for generic product discovery or price comparison.
`
이런 제한은 라우팅에 도움이 될 뿐 아니라, 제품과 QA 관점에서 여러분 App의 동작을 더 예측 가능하게 만들어 줍니다.
7. Apps 구성 패턴: pipeline, handoff, shared context
Multi‑App 시나리오에서는 실무적으로 세 가지 아이디어가 떠오릅니다:
- pipeline — 여러 App이 차례대로 진행(캘린더 → 선물 → 커머스), 각자 한 단계씩 수행;
- handoff — 한 App의 출력이 다음 App의 입력이 됨;
- shared context — 이런 전달은 앱 간 직접 HTTP 호출 없이 채팅의 공용 텍스트 컨텍스트를 통해 이루어짐.
이미 암시했듯이, Multi‑App 시나리오는 “App A가 HTTP로 App B를 호출”하는 마법이 아닙니다. 현재 ChatGPT Apps 구현에서는 격리가 꽤 강합니다. 앱들이 서로 직접 호출하지 않으며, 공용 텍스트 컨텍스트를 통해 커뮤니케이션합니다.
기본 패턴은 이렇게 정리할 수 있습니다:
- App A가 채팅에 텍스트나 JSON을 반환(종종 structuredContent/위젯 안에)합니다.
- 모델이 이 출력을 읽습니다.
- 다음 턴에서 모델은 App B를 호출할 수 있으며, A의 응답에서 세부 정보를 추출해 B의 도구 인자에 넣습니다.
이를 text/context handoff라고 부릅니다. “App A의 출력 → 모델 → App B의 입력”.
예시: CalendarApp + GiftGenius + CommerceApp
구체적인 시나리오를 살펴봅시다.
사용자: “내 상사가 내일 생일이야. 선물을 골라 주고 바로 구매까지 진행해줘.”
단계별:
-
모델은 먼저 날짜와 인물을 파악해야 한다고 이해합니다. 캘린더 App의 도구, 가령 corporate_calendar.list_upcoming_birthdays를 호출하고 다음과 같은 구조를 받습니다:
[ { "name": "Aleksey Bykov", "date": "2025-11-22", "relation": "manager" } ] -
다음으로 모델은 GiftGenius를 호출할 때라고 판단합니다. 캘린더에서 얻은 인자를 사용해 suggest_gifts를 호출합니다:
{ "recipientName": "Aleksey", "occasion": "birthday", "budget": 150, "relationship": "manager" }GiftGenius 위젯은 선물 캐러셀을 보여 주고, 텍스트 답변은 왜 이 아이디어들이 적절한지 설명합니다.
-
사용자가 한두 가지 옵션을 선택(위젯의 버튼 → widgetState)하면, 모델은 commerce‑App의 도구, 예를 들어 corp_checkout.create_gift_order를 호출해 선택한 SKU의 ID와 배송 주소를 전달합니다.
ChatGPT 관점에서는 세 개의 서로 다른 애플리케이션이지만, 사용자에게는 하나의 대화입니다. 이것이 잘 작동하려면 다음이 핵심입니다:
- 각 App 도구의 명확한 descriptions;
- 정돈된 이름(corporate_calendar.list_upcoming_birthdays, 단순한 list_events가 아님);
- 합의된 구조화 데이터 포맷(선물 아이디어를 commerce‑App이 이해할 수 있게 표현).
시각적 다이어그램
이 파이프라인은 다음과 같이 나타낼 수 있습니다:
sequenceDiagram
participant U as 사용자
participant C as ChatGPT (Router)
participant Cal as CalendarApp
participant G as GiftGenius
participant Com as CommerceApp
U->>C: 상사 생일 선물 골라서 구매까지 진행해줘
C->>Cal: tools.call(list_upcoming_birthdays)
Cal-->>C: [{ name, date, relation }]
C->>G: tools.call(suggest_gifts, { recipient, occasion, budget })
G-->>C: gift suggestions (+ widget)
C-->>U: 설명 + GiftGenius 위젯
U->>C: 2번 옵션이 좋아, 그거 사 줘
C->>Com: tools.call(create_gift_order, { skuId, address })
Com-->>C: Order confirmation
C-->>U: 완료, 주문이 접수되었습니다
GiftGenius 개발자로서 여러분의 과제는 이 합주에서 여러분의 목소리가 또렷하고 필요한 말만 하도록 만드는 것이지, 다른 목소리와 섞이게 하는 것이 아닙니다.
8. 상호운용성: 다른 App이 활용할 수 있는 응답 만들기
Multi‑App 세계에서는 단순히 “사람에게 보기 좋게 답하는 것”만으로는 부족합니다. 여러분의 toolOutput은 다른 애플리케이션(commerce‑App, 분석 에이전트, 워크플로 오케스트레이터 등)이 기계적으로 처리할 수 있어야 합니다.
이는 몇 가지 실천적 의미를 갖습니다:
- 도구의 응답에서 직렬화된 “사람 읽기용” 텍스트 대신 구조화된 JSON을 사용하세요.
- 안정적이고 이해하기 쉬운 필드를 유지하려고 노력하세요.
예를 들어, suggest_gifts의 결과를 다음과 같이 타입화할 수 있습니다:
export type GiftSuggestion = {
id: string;
title: string;
description: string;
price: number;
currency: string;
forPerson: string;
occasion: string;
purchaseUrl: string;
};
그리고 도구 응답에서는 이러한 객체 배열을 반환합니다:
{
"gifts": [
{
"id": "sku_123",
"title": "데스크톱 플라네타륨",
"description": "미니 별자리 프로젝터...",
"price": 89.99,
"currency": "USD",
"forPerson": "Aleksey",
"occasion": "birthday",
"purchaseUrl": "https://shop.example.com/sku_123"
}
]
}
GiftGenius 위젯은 이를 props로 받아 카드를 보기 좋게 렌더링하고, commerce‑App은 컨텍스트에서 이 JSON을 보고 id와 purchaseUrl을 이어받아 다음 체크아웃 단계로 진행할 수 있습니다.
Multi‑App 시나리오의 실무 경험은 이렇게 말해 줍니다. 좋은 App은 데이터를 사람의 눈뿐 아니라 다른 App도 “소화”할 수 있도록 반환합니다.
9. Multi‑App에 맞춘 GiftGenius의 실전 리팩터링
우리의 학습용 애플리케이션에서 몇 가지 구체적인 변경으로 요약해 봅시다.
manifest‑description 다듬기
openai-app.json(또는 Next.js 템플릿의 동등 파일)에 다음과 같은 설명이 있다고 합시다:
{
"name": "GiftGenius",
"description": "Gift assistant for finding and buying presents."
}
라우팅에 더 명확하게 바꿔봅시다:
{
"name": "GiftGenius",
"description": "Assistant for gift ideas and purchase flows. Use this app when the user asks what to gift a specific person or for a specific occasion within a budget. Do not use for generic online shopping or personal finance planning."
}
이제 이 텍스트만 봐도 이것이 일반 쇼핑, 재무 상담, 캘린더가 아니라는 것을 알 수 있습니다.
도구 descriptions 재작성
선물 검색 도구:
const suggestGiftsTool = {
name: "giftgenius_suggest_gifts",
description: `
Use this when the user asks for gift ideas for a specific person or group,
optionally with a budget or occasion.
Do not use for non-gift product recommendations or travel booking.
`
};
여러분의 카탈로그에서 SKU 상세를 끌어오는 도구(read‑only):
const getGiftDetailsTool = {
name: "giftgenius_get_gift_details",
description: `
Use this to fetch more details for a gift suggested earlier by GiftGenius,
for example when the user asks “tell me more about option #2”.
`,
annotations: { readOnlyHint: true }
};
구매 도구는 앞서 보았듯이 destructiveHint를 사용합니다.
_meta["openai/widgetDescription"] 업데이트
위젯에 이미 “구매” CTA가 있는 카드가 있다고 가정합시다. 이를 모델에 알려 줍시다:
const giftWidgetMeta = {
_meta: {
"openai/widgetDescription": `
설명, 가격, '구매' 버튼이 있는 선물 카드 목록을 표시합니다.
모델은 전체 목록을 텍스트로 반복하지 말고, 선택을 코멘트하며 의사결정을 돕는 데 집중해야 합니다.
`
}
};
이제 모델은 위젯에 이미 보이는 10개의 선물을 채팅에서 장황하게 나열하는 일을 줄이고, 설명과 논리에 집중할 것입니다. 이는 UX와 토큰 비용 모두에 유익합니다.
10. 미래 제품을 위한 Multi‑App 사고
“사용자의 유일한 App이 되기 위해 경쟁자를 모두 이기자” 모드에서 “거대한 생태계의 훌륭한 모듈이 되자” 모드로 사고를 전환하는 것이 중요합니다.
이 접근은 몇 가지 실질적 이점을 줍니다:
- 사용자와 Store 리뷰어에게 여러분의 App이 왜 필요한지, 언제 적절한지 설명하기 쉬워집니다.
- 모델의 라우팅 결정이 쉬워집니다. 혼란이 줄고 “엉뚱한” 호출이 줄어듭니다.
- 의도적으로 구성을 설계할 수 있습니다. 오늘은 캘린더와 커머스, 내일은 사내 HR 봇이나 내부 CRM과도요.
공식 discovery 가이드는 “one job per tool”을 설계하고, 메타데이터를 초기에 한 번 쓰고 끝나는 고정 텍스트가 아니라 테스트하고 갱신해야 하는 살아 있는 산출물로 다루라고 강조합니다.
모듈 20의 이전 주제에서 이미 해 둔 작업들 — golden 케이스, LLM evals, CI 실행 — 이 큰 도움이 됩니다. “채팅에 GiftGenius와 CalendarApp이 함께 있는” 시나리오로 케이스를 확장하고, 설명 변경이 App 선택과 응답 품질에 어떤 영향을 미치는지 추적할 수 있습니다.
11. Multi‑App 및 구성 작업에서의 흔한 실수
오류 №1: App 설명이 “나는 무엇이든 다 한다”.
manifest‑description에 “모든 작업을 위한 스마트 도우미” 같은 표현을 쓰면, 다른 App뿐 아니라 기본 ChatGPT와도 경쟁하게 됩니다. 라우터는 언제 꼭 여러분을 불러야 하고, 언제 기본 기능으로 충분한지 판단하기 어렵습니다. Multi‑App 세계에서는 “선물 추천”, “캘린더 관리”, “로그 분석”처럼 명확하고 좁은 목적을 가진 앱이 승리합니다.
오류 №2: 흐릿한 도구 descriptions와 이름 충돌.
get_data, process_request 같은 이름과 “사용자 데이터를 처리”한다는 설명은 모델을 헷갈리게 하기 딱 좋습니다. 여러 App이 있는 세계에서는 전혀 다른 도메인에서도 여러분의 tool이 호출되는 상황이 쉽게 생깁니다. 올바른 길은 도메인과 동작을 연결(giftgenius_get_gift_catalog, calendar.list_birthdays)하고, “Use this when… / Do not use when…”을 명확히 적는 것입니다.
오류 №3: _meta["openai/widgetDescription"]를 무시.
개발자는 흔히 description만 채우고 _meta는 지역화 정도로만 생각합니다. 그 결과 모델이 위젯이 무엇을 보여 주는지 이해하지 못해 UI를 텍스트로 중복하거나, 반대로 여러분의 위젯에 없는 “가격표가 있는 표”를 약속하기도 합니다. widgetDescription의 한두 줄이 이런 오해를 크게 줄여 줍니다.
오류 №4: 애너테이션 readOnlyHint/destructiveHint 부재.
모든 도구가 똑같이 “중립적”으로 보이면, 모델은 어떤 도구를 자주 안전하게 호출해도 되는지, 어떤 도구는 사용자 확인이 필요한지 구분하지 못합니다. 여러 App이 얽힌 다단계 시나리오에서는 특히 치명적입니다. 사용자 개입 없이 연속해서 여러 쓰기 작업이 일어날 수 있습니다. read‑only 도구는 표시하고, 결과를 초래하는/파괴적 작업은 명확히 구분하세요.
오류 №5: 사람만을 위한 응답, 다른 App을 고려하지 않음.
도구에서 “선물 목록”을 한 줄 텍스트로만 반환하는 것은 유혹적이지만, 그러면 다른 App이 그 결과를 활용하기 어렵습니다. id, price, currency, purchaseUrl, occasion처럼 명확한 필드를 갖춘 구조화된 JSON은 UI에도, 구성에도 보너스를 줍니다. 모델은 자연어 파싱 없이도 이 데이터를 다른 도구의 인자로 넣을 수 있습니다.
오류 №6: 한 App 안에 사용자가 필요로 할 만한 모든 것을 구현하려는 시도.
가끔 이렇게 욕심이 생깁니다. “어차피 GiftGenius를 만들었으니, 캘린더도 하고, 동료에게 메일도 보내고, 예산도 짜자.” 고립된 세계에서는 그럭저럭 가능할지 몰라도, Multi‑App 컨텍스트에서는 다른 잘 다듬어진 좁은 App들과 충돌하는 만능 콤바인이 됩니다. 스스로 합의하세요. 내 App은 X를 하고, 그것을 완벽하게 해낸다. 나머지는 다른 App의 책임이다. 이런 설계가 UX와 생태계 발전을 크게 단순화합니다.
오류 №7: 다른 App이 있는 환경에서의 동작을 테스트하지 않음.
개발자는 종종 Dev Mode의 “깨끗한” 채팅(다른 App 없음)에서만 앱을 테스트합니다. 하지만 Store에서 사용자는 앱을 열 개쯤 연결해 둘 수도 있고, 일부는 여러분의 App과 개념적으로 겹칩니다. 캘린더, 범용 쇼핑, 재무 등 이웃 App이 있는 테스트 시나리오를 꼭 만들어 golden 케이스를 돌려 보세요. 모델이 선물 관련 요청에서 GiftGenius를 제대로 선택하는지, 다른 참가자와 혼동하지는 않는지 확인해야 합니다.
GO TO FULL VERSION