CodeGym /행동 /ChatGPT Apps /한 프로젝트에서 Product Feed, Merchant 및 ACP 통합

한 프로젝트에서 Product Feed, Merchant 및 ACP 통합

ChatGPT Apps
레벨 14 , 레슨 4
사용 가능

1. 각 요소는 이미 따로따로 잘 동작한다…

지금쯤이면 ChatGPT를 중심으로 커머스 플로우가 어떻게 돌아가는지 감이 올 것입니다. 가맹점에는 프로덕트 피드가 있고, ACP 엔드포인트(/checkout_sessions 등)가 구현되어 있으며, Instant Checkout이 결제를 처리하고, 백엔드는 웹훅을 받아 주문을 생성합니다. 이 모든 것은 여러분의 ChatGPT 앱 없이도 동작할 수 있습니다. Product Feed + ACP 백엔드만으로 충분합니다.

여러분은 이미 다음을 할 수 있습니다:

  • OpenAI 사양에 따라 Product Feed를 구성하기;
  • Agentic Checkout / Delegated Payment를 설계하고 구현하기;
  • 선물 검색을 위한 MCP 도구와 위젯이 포함된 ChatGPT App 작성하기.

각 요소만 보면 훌륭하지만, 함께 놓이면 쉽게 “서비스 동물원”이 됩니다. 위젯은 위젯대로, MCP 서버는 MCP 서버대로, ACP 백엔드는 또 따로, 주문과 웹훅 로직은 또 다른 삶을 삽니다. 실제 구매를 디버깅하거나 이상한 버그를 고치려는 첫 순간, 팀 누구도 전체 그림을 제대로 보지 못하고 있다는 사실을 깨닫게 됩니다.

이 강의의 목표는 이 상태에서 벗어나 구현 가능한 일관된 아키텍처를 제공하는 것입니다. Product Feed가 ACP 백엔드와 어떻게 연결되는지, 그것들이 ChatGPT App과 위젯과는 어떻게 맞물리는지, 결제 서비스 제공자가 정확히 어디에 등장하는지, 그리고 이것들을 팀이 이해할 수 있는 구성요소(서비스, DB, API)로 어떻게 포장하는지 설명합니다.

동시에 무엇이 SPEC이라는 엄격한 표준이고, 무엇이 GiftGenius를 위한 우리의 아키텍처 선택인지 계속 강조하겠습니다.

인사이트: ChatGPT는 무료한 Google과 같다

ChatGPT는 사용자와의 상호작용에서 Google과 비슷하게 동작합니다. 스스로는 사용자로부터 수익을 내기 때문에, 여러분에게 관련성 높은 트래픽을 무료로 데려옵니다.

비즈니스 관점에서 이는 명확합니다. ChatGPT는 여러분의 상품을 위한 무료 “광고 채널”이 됩니다. 단, Product Feed와 ACP 백엔드를 연결해 두었을 때입니다. 모델은 사용자의 요청을 잘 충족시키는 상품이라면 여러분의 상품을 제안하며, 노출이나 클릭에 별도로 비용을 지불할 필요가 없습니다.

여기서 두 가지 실용적 시사점이 나옵니다:

  1. 기회의 창이 현재 잠정적으로 매우 저렴합니다. 지금 ACP 생태계의 경쟁은 높지 않고, 익숙한 광고 예산 없이도 상위 가격대에 진출할 수 있습니다. 항공, 부동산, 프리미엄 상품, 보험처럼 비싼 제품에서 높은 전환을 내는 트래픽이 사실상 공짜일 수 있는 드문 상황입니다.
  2. 가장 마진이 높은 버티컬부터 시작하는 것이 합리적입니다. 높은 객단가 카테고리에 접근할 수 있다면, 먼저 연결하는 것이 좋습니다:
    • 항공기, 요트, 빌라의 판매/임대;
    • 주택 및 프리미엄 부동산의 판매/임대;
    • 주얼리, 고가 시계, 보험 상품 및 서비스.

이는 “빨리 큰돈”을 보장하지는 않지만 비대칭을 만듭니다. 고가 세그먼트에서 품질 좋은 Product Feed와 신뢰할 수 있는 ACP 백엔드를 가장 먼저 구축한 팀은, 이 채널이 저평가되어 사실상 무료인 동안 비례 이상으로 큰 이익을 얻을 것입니다.

2. GiftGenius 레퍼런스 아키텍처: 큰 그림

먼저 상위 개요를 봅시다. 이전 모듈의 전체 그림을 떠올려 보세요. 사용자가 ChatGPT에 글을 쓰고, 모델이 여러분의 도구를 호출하며, 커머스 레이어는 별도의 백엔드에서 동작합니다.

GiftGenius의 주요 블록을 정리합니다.

첫째, 사용자와 대화를 이끌고 필요시 GiftGenius 앱을 연결하는 ChatGPT UI와 GPT 모델(혹은 아예 App 없이 Product Feed만으로 동작).

둘째, GiftGenius 위젯(Next.js + Apps SDK)입니다. 선물 카드와 필요에 따라 체크아웃 진행 상태를 보여줍니다. window.openai 샌드박스에서 동작하며 실제 결제 정보는 모릅니다.

셋째, MCP 레이어입니다. 카탈로그(Product Feed) 기반 선물 검색과 경우에 따라 주문 이력 조회를 위해 모델에게 도구를 제공합니다.

넷째, 커머스 / ACP 백엔드입니다. 이 백엔드는 다음을 수행합니다:

  • 상품과 SKU에 대한 단일 소스 오브 트루스로서 Product Feed를 읽습니다;
  • Agentic Checkout Spec을 구현합니다(/checkout_sessions, 웹훅, 상태 등);
  • Delegated Payment Spec에 따라 결제 서비스 제공자(예: Stripe)와 통신합니다.

다섯째, 카탈로그(피드가 DB에서 생성된다면)와 주문, 보조 구조(사용자, 설정 등)를 위한 데이터베이스입니다.

그리고 마지막으로 결제 서비스 제공자(PSP)입니다. 결제 데이터를 보관·처리하고 결제 결과에 대한 웹훅을 보냅니다.

이를 도식화하면 다음과 같습니다:

graph LR
  U[ChatGPT의 사용자] --> GPT[GPT 모델]
  GPT -->|렌더링| W[GiftGenius Widget
Next.js + Apps SDK] GPT -->|MCP tools| MCP[MCP 서버
선물 검색] MCP --> PF["Product Feed
(DB/JSON)"] GPT -->|ACP HTTP| ACP[GiftGenius Commerce Backend
Agentic Checkout] ACP --> ORDERS[주문 DB] ACP --> PSP["결제 서비스 제공자
(Stripe 등)"] PSP --> ACP ACP -->|webhooks/이벤트| GPT

이 다이어그램은 GiftGenius 아키텍처를 하나의 구현 예로 묘사합니다. Product Feed 형식, /checkout_sessions 계약, Delegated Payment 프로토콜은 ACP 표준의 일부로 남습니다. 서비스 배치, DB 스키마, 프로세스 분리는 여러분의 아키텍처 선택입니다.

3. Product Feed, ACP, 위젯은 논리적으로 어떻게 연결되는가

화살표에 휘둘리지 않으려면 한 가지 원칙을 고정하면 됩니다. 상품에 대한 단 하나의 단일 소스 오브 트루스를 갖는 것입니다.

GiftGenius에서는 PostgreSQL의 products + skus 테이블이 그 역할을 맡습니다. 여기서 여러분은:

  1. OpenAI 사양에 따라 Product Feed를 생성합니다(직접 또는 덤프를 통해).
  2. MCP 도구(예: search_gifts)를 위한 검색 인덱스를 구축합니다.
  3. ACP 백엔드의 요청을 검증합니다 — 들어온 sku_id가 실제로 존재하며 올바른 가격과 통화를 갖는지 확인합니다.

이렇게 MCP 검색과 ACP 체크아웃이 동일한 데이터를 바라보고, 위젯은 MCP 도구 혹은 ACP(예: 주문 정보)에서 전달된 결과를 보여줄 뿐입니다.

이를 하나의 카탈로그에 대한 두 개의 “창”으로 비유할 수 있습니다. 하나는 검색과 추천을 위한 창, 다른 하나는 구매를 위한 창입니다. 이 창들이 서로 다른 DB를 본다면 끝없는 비동기화 문제를 만나게 됩니다.

4. 데이터 모델링: Product Feed에서 주문까지

GiftGenius 리포지토리에 함께 살 TypeScript 타입부터 시작합시다(예: src/domain/commerce.ts). 이 타입들은 사양의 문자 그대로는 아니지만, 앱에 편리한 형태로 핵심 아이디어를 반영합니다.

// src/domain/commerce.ts

export interface ProductSku {
  id: string;          // 안정적인 SKU ID (Product Feed와 동일)
  title: string;       // 사람이 읽을 수 있는 이름
  priceCents: number;  // 센트 단위 가격
  currency: string;    // ISO 코드, 예: "usd"
}

export type CheckoutStatus = "pending" | "succeeded" | "failed";

export interface CheckoutSession {
  id: string;
  skuId: string;
  totalCents: number;
  currency: string;
  status: CheckoutStatus;
}

여기서 CheckoutSessionskuId 참조와 고정 통화/금액을 명시적으로 포함했습니다. 이는 우리의 내부 모델입니다. 실제 Agentic Checkout Spec은 더 풍부하지만, 기본 아이디어는 같습니다. 세션이란 “무엇을 얼마에 어떤 상태로”입니다.

다음으로 주문 타입이 필요합니다:

export interface Order {
  id: string;
  userId: string;
  skuId: string;
  totalCents: number;
  currency: string;
  checkoutSessionId: string;
  status: "awaiting_payment" | "paid" | "canceled" | "refunded";
}

여기에는 이전 모듈의 공통 엔터티: intent, checkout_session, order의 영향이 보입니다. 이 학습 프로젝트에서는 엔터티를 늘리지 않기 위해 intent와 order를 약간 합치되, checkoutSessionId와의 연결은 유지합니다.

5. GiftGenius 위젯이 커머스 세계를 ‘엿보는’ 방법

중요한 점: 위젯은 스스로 결제 모듈로 직접 호출하지 않으며 ACP 세부사항을 알 필요도 없습니다. 역할은 백엔드에서 계산·고정된 상태를 사용자에게 보여주는 것입니다.

가장 단순하고 유용한 시나리오: 성공적으로 구매한 뒤 사용자가 채팅으로 돌아와 “GiftGenius에서 내 최근 주문을 보여줘”라고 묻는 경우입니다. GPT는 get_user_orders 같은 MCP 도구를 호출하여 백엔드에 접근하고, 위젯은 목록을 보여줍니다.

최근 주문을 반환하는 Next.js API 라우트를 간단히 가정해 봅시다:

// app/api/orders/recent/route.ts

import { NextRequest, NextResponse } from "next/server";
import { getRecentOrdersForUser } from "@/lib/orders";

export async function GET(req: NextRequest) {
  const userId = req.headers.get("x-giftgenius-user-id")!;
  const orders = await getRecentOrdersForUser(userId);
  return NextResponse.json({ orders });
}

getRecentOrdersForUser 함수는 이미 커머스 레이어에 있으며, DB와 상호작용하고 주문 구조를 이해합니다. 위젯은 window.fetch를 통해 이 라우트를 호출할 수 있고(이전 모듈에서 이미 사용), 구매 카드를 보여줄 수 있습니다.

“MCP 도구 → 여러분의 API → 주문 DB → 위젯” 조합은, 위젯이 단지 백엔드 상태를 렌더링할 뿐임에도 불구하고, 사용자에게 App이 구매 이력을 “기억”하는 듯한 경험을 제공합니다.

6. Next.js 스타일의 간단한 ACP 엔드포인트 구현

이제 핵심 ACP 엔드포인트 중 하나인 checkout_session 생성에 대한 학습용 구현을 개략적으로 살펴봅니다. 사양의 계약은 꽤 풍부하지만, 강의에서는 본질에 집중합니다. skuId가 들어오면 피드/DB로 검증하고, 세션을 생성해 ID와 금액을 반환합니다.

예를 들어 POST /api/checkout-sessions 라우트를 둡니다:

// app/api/checkout-sessions/route.ts

import { NextRequest, NextResponse } from "next/server";
import { findSkuById, createCheckoutSession } from "@/lib/checkout";

export async function POST(req: NextRequest) {
  const body = await req.json();          // { skuId: string }
  const sku = await findSkuById(body.skuId);

  if (!sku) {
    return NextResponse.json(
      { error: "SKU not found" },
      { status: 400 },
    );
  }

  const session = await createCheckoutSession(sku);
  return NextResponse.json({ session });
}

여기에는 몇 가지 중요한 포인트가 있습니다.

첫째, 커머스 레이어가 Product Feed/DB와 대조하는 위치가 바로 여기입니다. findSkuById는 피드를 생성하는 것과 동일한 소스를 봐야 합니다. 우리는 GPT나 위젯 등 “공중에서” 온 어떤 값도 신뢰하지 않습니다.

둘째, ChatGPT/ACP 클라이언트에 필요한 것만 반환합니다. 세션 ID, 금액, 통화, 상태(기본적으로 pending 또는 선택한 용어에 따라 not_ready_for_payment). 실제 ACP에는 사용 가능한 결제 수단과 배송 정보 등 더 많은 필드가 있지만, 학습 예시는 초기 세션 생성에 집중합니다.

셋째, 이런 라우트는 계약 테스트로 커버하기 좋습니다. 내일 Product Feed 구조가 바뀐다면, findSkuByIdcreateCheckoutSession 테스트가 사용자가 이상한 오류를 보기 전에 문제를 잡아야 합니다.

7. ACP 세션과 결제 서비스 제공자(PSP)의 연결

지금까지는 결제 서비스 제공자(PSP)를 다루지 않았습니다. 실제 통합에서는 대략 다음이 일어납니다(단순화된 시나리오).

먼저 ChatGPT가(ACP를 통해) 여러분의 POST /checkout_sessions를 호출합니다. 백엔드는 자체 DB에 로컬 세션을 만듭니다. 사용자가 Instant Checkout UI에서 결제를 확정하면, 플랫폼은 특정 가맹점과 금액에 대한 위임 결제 토큰(Shared Payment Token)을 PSP에서 요청합니다. 이 토큰은 complete 요청(혹은 Delegated Payment Spec에 정의된 유사 호출)으로 여러분에게 전달됩니다.

그 다음 여러분은 실제 결제 데이터에 접근하지 않고, 토큰을 사용해 PSP에서 결제를 생성합니다. PSP는 결과를 웹훅으로 보내고, 여러분은 주문과/또는 체크아웃 세션의 상태를 갱신합니다.

학습 코드에서는 이 단계를 모의로 제한할 수 있습니다. 예를 들어 completeCheckoutSession 함수는 다음과 같을 수 있습니다:

// src/lib/checkout.ts

export async function completeCheckoutSession(sessionId: string, spt: string) {
  // 실제로는 위임된 토큰(SPT)으로 PSP API를 호출합니다
  const paymentOk = await mockChargeWithToken(spt);

  return paymentOk
    ? { status: "succeeded" as const }
    : { status: "failed" as const };
}

PSP 호출과 Shared Payment Token 사용은 Delegated Payment 표준의 일부이며, mockChargeWithToken 함수는 이를 모사하는 학습용 아키텍처 레이어입니다.

8. GiftGenius 엔드투엔드 플로우: 요청에서 결제 완료 선물까지

이제 모든 것을 단계 시퀀스로 모아 봅시다. 이것이 우리가 모든 레이어를 결합하는 바로 그 “실전” GiftGenius 스토리입니다. 서로 다른 두 세계를 섞지 않기 위해, 각기 분리해서 보겠습니다.

시나리오 A: App 없이, Product Feed + ACP만

이 시나리오에서는 Product Feed와 ACP 백엔드는 있지만, ChatGPT App과 위젯은 없습니다. 전형적인 Instant Checkout 가맹점입니다.

사용자가 ChatGPT에 “$50 이하의 디지털 선물 추천해줘”라고 씁니다. GPT는 여러분의 Product Feed를 이용해 적절한 SKU를 찾고, 자체 네이티브 UI로 쇼핑 카드를 보여줍니다. 아직 여러분의 React 코드는 전혀 없습니다 — 카드는 전적으로 ChatGPT가 렌더링합니다.

사용자가 이런 카드 중 하나의 “Buy” 버튼을 클릭합니다. 이 클릭은 ChatGPT 자체가 처리합니다. 플랫폼은:

  1. Product Feed를 바탕으로 line_items를 구성합니다.
  2. Agentic Checkout Spec에 따라 여러분의 POST /checkout_sessions를 호출합니다.
  3. 사용자에게 Instant Checkout UI(결제 수단, 주소 등)를 표시합니다.
  4. 확정 후 PSP에서 Shared Payment Token을 받고, 여러분의 .../complete를 호출합니다.
  5. 여러분에게서 최종 checkout_session 상태를 받고, 필요 시 주문 웹훅을 대기합니다.

여러분의 코드 관점에서 여기서는 ACP 엔드포인트와 Product Feed만 동작합니다. Apps SDK, window.openai, 위젯은 존재하지 않습니다. 그리고 이는 완전히 유효한 “순수” ACP 가맹점 시나리오입니다.

시나리오 B: ChatGPT App과 GiftGenius 위젯 포함

이제 ChatGPT App과 GiftGenius 위젯을 추가합니다. Product Feed와 ACP 백엔드는 여전히 검색과 결제를 담당합니다. 차이는 우리만의 UI와 App 내부 단계 로직이 생긴다는 점입니다.

대화를 가정해 봅시다. 사용자가 ChatGPT에 “엄마를 위한 50달러 이하 선물을 골라줘”라고 씁니다. GPT는 커머스 요청임을 이해하고 GiftGenius 앱 사용을 제안합니다. 위젯은 나이, 관심사, 국가 같은 몇 가지 보조 질문을 합니다. 이후 GPT는 필터와 함께 MCP 도구 search_gifts를 호출하고, MCP 서버는 카탈로그(DB 또는 준비된 인덱스)에 접근해 적절한 SKU를 찾고 구조화된 형태로 반환합니다.

GPT는 이 데이터를 위젯에 전달하고, 위젯은 자체 카드(React 컴포넌트, 캐러셀 등)로 보여줍니다. 이는 표준 ChatGPT 쇼핑 UI가 아닌 여러분의 디자인과 UX입니다.

사용자가 위젯에서 “구매” 버튼을 클릭하면, 시나리오 A와는 다른 일이 벌어집니다. 이 클릭은 위젯이 처리합니다:

  1. 위젯은 사용자가 선택한 SKU를 파악합니다.
  2. 자체 API(예: POST /api/checkout-sessions)로 백엔드를 호출해 checkout_session을 생성(또는 이미 준비된 세션 ID를 수신)합니다.
  3. 그런 다음 위젯은 Apps SDK의 런타임 메서드를 호출합니다:
    // 최신 메서드 시그니처는 Apps SDK 문서를 참고하세요
    await window.openai.requestCheckout({
      checkoutSessionId: session.id, ...
    });
    

    이 호출은 위젯의 주도입니다. ChatGPT에게 “이 checkout_session에 대해 Instant Checkout을 열 시간”이라는 신호입니다.

그 다음 ChatGPT 플랫폼은 시나리오 A와 무대 뒤에서 매우 유사하게 동작합니다:

  • 사용자에게 네이티브 Instant Checkout UI를 보여줍니다;
  • PSP에서 Shared Payment Token을 받습니다;
  • 여러분의 ACP 세션 완료 엔드포인트(.../complete)를 호출합니다;
  • 여러분의 백엔드에서 오는 웹훅 수신·처리에 관여합니다.

즉, 시나리오 B에서는 위젯이 Apps SDK를 통해 체크아웃을 시작하고, ACP 호출( checkout_session 생성/완료)은 그 전(백엔드에서 여러분이 직접 세션을 만들 때)이거나 requestCheckout 이후에 일어나지만, 항상 서버 사이드에서 처리됩니다.

동시에 위젯은 여러분의 API(/api/orders/...)와 MCP 도구를 바탕으로 “구매 진행”, 상태, 주문 프리뷰를 병렬로 보여줄 수 있습니다.

시나리오 B를 다이어그램으로 표현하면 다음과 같습니다:

sequenceDiagram
  participant User as 사용자
  participant GPT as ChatGPT / GPT
  participant W as GiftGenius Widget
  participant MCP as MCP 서버
  participant ACP as Commerce Backend
  participant PSP as 결제 서비스 제공자

  User->>GPT: "50달러 이하의 선물을 추천해줘"
  GPT->>MCP: search_gifts(...)
  MCP-->>GPT: SKU 목록
  GPT->>W: 카드 렌더링용 데이터
  User->>W: "구매" 클릭
  W->>ACP: POST /api/checkout-sessions (skuId)
  ACP-->>W: checkout_session (id, 금액, 통화)
  W->>GPT: window.openai.requestCheckout({ checkoutSessionId })
  GPT->>User: Instant Checkout UI
  User->>GPT: 결제 확인
  GPT->>PSP: Shared Payment Token 요청
  PSP-->>GPT: SPT
  GPT->>ACP: complete(sessionId, SPT)
  ACP->>PSP: charge(SPT)
  PSP-->>ACP: 결제 결과
  ACP->>GPT: 주문 상태
  GPT->>User: 성공/실패 결제 알림 메시지

시나리오 A와의 핵심 차이:

  • A에서는 카드와 “Buy” 버튼을 ChatGPT 자체가 렌더링하며, ACP 호출도 ChatGPT가 직접 시작합니다.
  • B에서는 카드와 “구매” 버튼을 여러분의 위젯이 렌더링하고, window.openai.requestCheckout(...)를 호출하는 것도 위젯입니다. 그 후 ChatGPT가 백그라운드에서 여러분의 ACP 백엔드 및 PSP와 통신합니다.

인사이트

ChatGPT의 SDK 문서에 따르면 곧 앱에 수익화가 도입됩니다. 실제로 그렇게 될 것입니다. 위젯에는 아직 공개되지 않은 여러 메서드가 이미 준비되어 있으며, 가장 흥미로운 것이 requestCheckout()입니다.

호출은 다음과 같습니다:

window.openai.requestCheckout({
  id: "checkout_session_123",

  payment_provider: {
    merchant_id: "stripe",
    supported_payment_methods: ["card"]
  },
   ...
}

이 호출은 사용자가 결제를 완료할 수 있는 대화창을 표시합니다. 따라서 수익화가 이미 켜져 있는 것처럼 앱을 설계하세요. 여러분이 작업을 마칠 때쯤이면 실제로 그렇게 되어 있을 것입니다.

9. 강의용 미니 구현: 모놀리식 백엔드

아키텍처 모듈에서 이미 다룬 바와 같이, 모든 것을 하나의 서비스로 할지, MCP 서버/커머스 백엔드/별도 결제 통합 서비스를 처음부터 분리할지 고민이 있습니다. 교육 목적이라면 대개 “거의 모놀리식”으로 충분합니다. 하나의 리포지토리, 하나의 배포지만, 로직은 레이어별로 깔끔히 분리합니다.

학습용 GiftGenius는 다음과 같이 구성할 수 있습니다. Next.js 애플리케이션에서:

  • 위젯은 app/widget/page.tsx에 위치;
  • ACP 엔드포인트는 app/api/checkout-sessions 및 인접 라우트에 위치;
  • MCP 도구는 app/api/mcp/route.ts 또는 별도 폴더에 위치;
  • 주문 처리는 src/lib/orders.ts, src/lib/checkout.ts 등 관련 모듈에 위치.

물리적으로는 하나의 서버(특히 dev/staging 단계)지만, 논리적으로는 이미 세 가지 역할(UI/위젯, MCP/도구·리소스, ACP/커머스 백엔드)로 사고합니다.

이후 프로덕션 모듈에서는 이 “모놀리식”이 여러 서비스와 환경으로 분리되고, 그 앞에 MCP Gateway가 등장합니다. 하지만 모듈 14 수준에서는 “레이어가 올바른 모놀리식”만으로도 매우 그럴듯한 아키텍처를 얻을 수 있습니다.

10. 실습 과제: ACP를 중심으로 여러분의 아키텍처 설계

위에서 설명한 내용을 이론으로만 남기지 않으려면, 지금 바로 여러분의 도메인에 적용해 보는 것이 좋습니다. 강의 범위에서는 두 가지 미니 연습을 할 수 있습니다.

첫째, 자체 시나리오를 선택하세요. SaaS 구독, 예약, 음식 배달, 온라인 강의 — 상품/서비스, 가격, 합리적인 체크아웃이 있는 어떤 케이스든 괜찮습니다. 페이즈 모델을 떠올리세요: discovery → decision → checkout → post‑payment.

둘째, GiftGenius 아키텍처를 바탕으로 자유 양식으로 작성하세요. Product Feed를 어떻게 구성할지(SKU와 가격이 어디에 있고 누가 업데이트하는지), ACP 계약을 어디에 구현할지(별도 서비스 또는 기존 백엔드 일부), 결제 서비스 제공자를 어떻게 연결할지, 위젯(있다면)이 MCP와 Apps SDK를 통해 이 모든 것과 어떻게 상호작용할지를 설명합니다.

프로젝트가 시나리오 A(앱 없는 Instant Checkout)만 쓸지, 시나리오 B(App + 위젯)만 쓸지, 아니면 두 시나리오를 모두 동시에 쓸지를 명확히 정리하는 것도 유익합니다. 이런 텍스트 초안만으로도 실제 통합 단계에서의 불확실성을 크게 줄일 수 있습니다.

11. Product Feed, ACP, 위젯 통합 시 흔한 실수

실수 1: 검색용 카탈로그와 체크아웃용 카탈로그가 따로임.
팀이 먼저 GPT용 “빠른 검색” 피드(예: 작은 JSON)를 띄운 다음, 주문용 커머스 DB를 따로 만드는 경우가 있습니다. 공통 ID와 공통 업데이트 로직으로 묶지 않으면, GPT가 더 이상 구매할 수 없거나 가격이 바뀐 상품을 사용자에게 제안할 수 있습니다. 정답은 단 하나의 소스 오브 트루스입니다. 여기서 Product Feed와 ACP 엔드포인트를 위한 내부 테이블이 함께 파생되어야 합니다.

실수 2: GPT나 위젯에서 들어온 데이터를 신뢰함.
checkout_sessionskuId와 가격이 들어오면 그대로 믿고 싶어집니다. 하지만 모델은 쉽게 상상하거나 SKU를 혼동할 수 있고, 사용자는 요청을 변조하려 시도할 수 있습니다. 들어오는 데이터를 Product Feed/DB와 대조하지 않으면 잘못된 상품을 잘못된 가격에 팔 위험이 있습니다. 모든 ACP 엔드포인트는 카탈로그의 1차 저장소를 기준으로 검증부터 시작해야 합니다.

실수 3: 위젯과 커머스 백엔드의 역할을 혼동함.
종종 프런트엔드에서 결제 SDK를 직접 호출하고, Stripe에서 세션을 만들고, 일반 웹사이트처럼 행동하는 습관이 남아 있습니다. ChatGPT Apps 문맥에서는 보안 모델을 해치고 ACP에 반합니다. 결제 플로우는 ChatGPT와 여러분의 커머스 백엔드를 통해 진행되어야 하며, 위젯은 상태를 표시하고 requestCheckout 같은 이벤트만 보냅니다. 위젯이 결제 영역을 너무 많이 알면 복잡성과 리스크가 모두 커집니다.

실수 4: ACP 계약을 과도하게 단순화함.
학습 예시에서는 skuId, 금액, 상태만 남겨 세부에 빠지지 않도록 했습니다. 문제가 되는 순간은 이 “데모 계약”이 슬그머니 프로덕션으로 흘러들 때입니다. 주소, 세금, 배송 방법, 프로모션 코드 등의 필드가 부족하다는 걸 뒤늦게 깨닫고, 무질서하게 “붙이기” 시작하게 됩니다. 실제 시나리오를 감당할 수 있도록 내부 모델을 처음부터 여유 있게 설계하는 편이 낫습니다. 일부 필드는 한동안 쓰이지 않더라도 말이죠.

실수 5: 주문과 사용자의 연결 고리 부재.
데모에서는 orderIdskuId만으로 충분하다고 생각하기 쉽습니다. 하지만 사용자가 일주일 뒤 돌아와 “내 구매를 보여줘”라고 말하는 순간이 옵니다. userId(혹은 다른 안정적인 식별자)를 주문과 체크아웃 세션에 처음부터 포함하지 않으면, 나중에 마이그레이션과 복잡한 브리지를 만들게 됩니다. ChatGPT 중심 커머스 아키텍처는 거의 항상 GPT가 현재 대화를 사용자 주문 이력과 연결할 것을 전제합니다 — 이를 미리 고려하세요.

실수 6: 웹훅과 멱등성의 중요성을 과소평가함.
이 강의에서는 웹훅을 언급만 했고, 자세한 내용은 다음 모듈에서 다룹니다. “웹훅은 한 번 오면, 주문 업데이트하고 끝”이라고 생각하기 쉽습니다. 실무에서 결제 시스템은 이벤트를 재시도하는 경향이 있고, 네트워크는 응답을 잃어버립니다. checkoutSessionIdpaymentId 기준으로 주문과 체크아웃 세션을 멱등적으로 설계하지 않으면, 이중 청구, 중복 주문, PSP와 여러분의 DB 간 비정상적인 불일치가 발생할 수 있습니다.

실수 7: Product Feed의 정책/제한을 무시함.
빠른 데모 피드를 만들다 보면, 연령 제한, 국가별 제한, 금지 카테고리 등의 “사소한 것들”을 잊기 쉽습니다. 그 결과 GPT가 사용자에게 해당 지역이나 연령에서 팔 수 없는 상품을 즐겁게 제안하는 일이 생깁니다. 정책과 제한 관련 필드는 처음부터 설계하고 채워야 합니다. 당장은 무해한 디지털 선물만 판매하더라도 말이죠.

1
설문조사/퀴즈
결제: ACP 및 Instant Checkout, 레벨 14, 레슨 4
사용 불가능
결제: ACP 및 Instant Checkout
커머스: Product Feed, ACP 및 Instant Checkout
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION