CodeGym /행동 /ChatGPT Apps /가벼운 부하 테스트와 피드 데이터 품질

가벼운 부하 테스트와 피드 데이터 품질

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

1. 왜 ChatGPT App에 부하 테스트가 필요할까요?

전통적인 웹에서 부하 테스트는 종종 “수백만 RPS, 거대한 클러스터, SRE를 위한 피자” 같은 이미지와 연관됩니다. ChatGPT App과 MCP 서버의 현실은 더 단순하고, 다행히 더 저렴합니다. 기본적으로 여러분은 이미 SLO에 익숙하지만, SLO/observability와 피드 품질이 부하 하에서 어떻게 상호작용하는지 살펴보겠습니다.

핵심 특징: ChatGPT는 tool call이 끝날 때까지 다음 답변 생성을 기다립니다. 사용자는 멋진 토큰 스트림을 보지만, 모델이 도구 호출을 결정하는 순간 스트림의 마법은 끝나고 — 백엔드가 응답할 때까지 기다리게 됩니다. MCP나 ACP 서버가 목표 2–4초 대신 가끔 8–10초에 응답한다면, UX는 “마법 같은 비서”에서 “또 하나의 느린 사이트”로 바뀝니다.

게다가 엄격한 타임아웃 예산이 있습니다: 도구 호출의 경우 OpenAI는 상한을 수십 초 수준으로 잡고 있습니다(정확한 수치는 모드에 따라 다르지만, 30–60초 범위를 생각하면 되고 UX 관점에서는 5–10초 내가 이상적입니다). 피크 부하에서 tool calls가 갑자기 25–30초에 맞춰지기 시작하면 형식상 한계 내일 수는 있지만, 사용자 입장에서는 이미 “망가졌”습니다.

두 번째 포인트: 중요한 것은 추상적인 RPS가 아니라 동시성입니다. Store에 있는 App의 경우 50–100명의 동시 활성 사용자 정도는 충분히 현실적입니다. 바로 이것을 확인해야지 “합성 GET /health 50k RPS를 버티는가”를 볼 필요는 없습니다.

그리고 마지막으로, ChatGPT App은 스택입니다:

flowchart LR
  User --> ChatGPT
  ChatGPT -->|tools/call| MCP["MCP 서버 GiftGenius"]
  MCP --> DB["선물 피드 DB"]
  MCP --> ACP["Checkout / ACP 백엔드"]
  ACP --> PSP["결제사 / Stripe"]

이 스택이 작지만 현실적인 부하에서 어떻게 동작하는지 점검하지 않으면, 어떤 프로모션 메일이나 Store 큐레이션에 노출되는 순간 “LLM 제품을 이렇게 만들면 안 됩니다”라는 슬라이드가 되어버릴 수 있습니다.

이 강의에서 말하는 “가벼운 부하 테스트”는 짧은 실행(보통 1–10분)으로 다음을 확인합니다:

  • 시스템이 예상 피크 동시 접속을 견디는가;
  • p95/p99 지연 시간이 SLO를 넘지 않는가;
  • 외부 API에서 오류, 타임아웃, rate‑limit가 쏟아지지 않는가.

그리고 동시에 두 번째 품질 축 — 상품 피드(product feed, 이하 “피드”)의 데이터를 살펴봅니다. 피드가 없으면 GiftGenius는 “Gift”도 “Genius”도 아닙니다.

이 강의에서는 먼저 MCP/ACP에 대한 가벼운 부하 테스트(무엇을 어떻게 때릴지, 어떤 메트릭을 볼지)를 정리하고, 그다음 observability(지연 시간, 오류, 리소스, 웹훅, 로그)에 접목합니다. 후반부에서는 피드 품질과 그것이 부하 상황에서 어떻게 뜻밖의 문제를 일으키는지 이야기합니다.

2. 무엇을 때릴까: ChatGPT가 아니라 자신의 API

혼동하지 않도록 한 가지를 확고히 합시다: 부하 테스트는 ChatGPT UI가 아니라 우리 백엔드 — MCP 서버, ACP 엔드포인트, 웹훅 — 에 직접 수행합니다.

이유는 여러 가지입니다.

  • 첫째, 비용 절감. 실제 tool calls를 ChatGPT를 통해 돌리면 토큰 비용을 내면서 동시에 ChatGPT의 한계에 걸리게 됩니다. 하지만 여러분이 테스트하는 것은 자신의 코드입니다.
  • 둘째, 예측 가능성. /mcp/api/checkout을 직접 호출하면, 모델이 지금 도구를 호출할지 말지에 좌우되지 않고 시나리오를 통제할 수 있습니다.
  • 셋째, 투명성. 부하 상황에서는 “5분에 MCP로 2000개의 요청, 지연 시간 분포, CPU 그래프”처럼 명확히 보고 싶습니다. ChatGPT를 통해 부하를 넣으면 추가적인 노이즈와 제한이 그림을 더 복잡하게 만듭니다.

GiftGenius의 전형적인 부하 테스트 엔드포인트 구성:

  • JSON‑RPC tools를 구현하는 MCP 서버 엔드포인트(/mcp 또는 유사한 경로);
  • checkout 생성/완료를 위한 1–2개의 ACP 엔드포인트(결제사의 sandbox 모드에서);
  • 가능하다면 — 결제사에서 오는 웹훅을 처리하는 엔드포인트(이벤트 피크에서의 동작 관찰).

우리는 Next.js 16 백엔드 위에 MCP 서버가 /api/mcp로, 그리고 ACP 서버의 엔드포인트가 /api/checkout/create로 노출되어 있다고 가정합니다.

3. GiftGenius를 위한 미니 smoke‑load 시나리오

프로덕트 매니저들이 밝은 미래를 믿으며 말합니다: “현실적인 피크는 동시 사용자 50명, 각 사용자가 들어와 선물을 고르고, 때로는 결제까지 간다.”

가벼운 부하 테스트에는 30–50명의 “가상 사용자”(VU)를 모델링하면 충분합니다. 각 사용자는 다음 순서를 수행합니다:

  1. giftgenius.search_gifts 도구 호출(프로필/예산 기반 선물 검색).
  2. 결과 중 두 개 상품에 대해 giftgenius.get_gift_details 호출.
  3. (가끔) 하나의 상품에 대해 ACP 엔드포인트 create_checkout_session 호출.

모든 것은 ChatGPT 없이, 우리 MCP/ACP에 대한 HTTP 직접 호출로 진행합니다.

JSON‑RPC로 MCP 호출

MCP에 대한 요청 본문 예시(단순화):

const body = {
  jsonrpc: "2.0",
  id: "test-" + Math.random(),
  method: "tools/call",
  params: {
    toolName: "giftgenius.search_gifts",
    arguments: {
      occasion: "birthday",
      budget: 50,
      interests: ["sport", "books"],
    },
  },
};

실제 프로젝트에서는 구조가 조금 다를 수 있지만 원리는 같습니다. 하나의 JSON‑RPC 메서드 안에 tool과 인자가 들어갑니다.

4. TypeScript로 간단한 부하 스크립트 작성

첫 단계로 시나리오 중 가장 간단한 부분 — MCP에 대한 giftgenius.search_gifts 호출 — 을 구현합니다. 먼저 /api/mcp에 해당 요청을 보내고 지연 시간을 측정하는 최소 Node.js/TypeScript 스크립트를 만든 뒤, checkout과 더 복잡한 경로를 추가합니다.

기본 HTTP 클라이언트

.envMCP_URL=http://localhost:3000/api/mcp가 있다고 가정합니다.

// scripts/loadTest.ts
import "dotenv/config";

const MCP_URL = process.env.MCP_URL!;

async function callSearchGifts() {
  const body = {
    jsonrpc: "2.0",
    id: `search-${Date.now()}-${Math.random()}`,
    method: "tools/call",
    params: {
      toolName: "giftgenius.search_gifts",
      arguments: { occasion: "birthday", budget: 50 },
    },
  };

  const started = Date.now();
  const res = await fetch(MCP_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  const latencyMs = Date.now() - started;
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return latencyMs;
}

여기서 JSON 응답의 간단한 파싱을 추가할 수도 있지만, latency/error rate 목적에는 이 정도로 충분합니다.

여러 요청의 동시 실행

동시 요청 수를 제어해야 합니다. 단순화를 위해 고정 개수의 “가상 사용자”를 두고, 각자가 N번 연속 요청을 수행하도록 합니다.

async function runVirtualUser(iterations: number) {
  const latencies: number[] = [];
  for (let i = 0; i < iterations; i++) {
    try {
      const ms = await callSearchGifts();
      latencies.push(ms);
    } catch (e) {
      console.error("Error in VU:", e);
      latencies.push(-1); // 오류로 표시
    }
  }
  return latencies;
}

이제 예를 들어 20명의 가상 사용자를 실행할 수 있습니다:

async function main() {
  const users = 20;
  const iterations = 10;

  const tasks = Array.from({ length: users }, () =>
    runVirtualUser(iterations),
  );

  const results = await Promise.all(tasks);
  const all = results.flat();
  // ...메트릭 계산
}

main().catch((e) => console.error(e));

이것만으로도 MCP에 약 200회의 호출이 발생하며, 일부는 병렬로 실행되어 꽤 높은 동시성을 제공합니다.

p95와 error rate 계산

퍼센타일과 오류율 계산을 위한 작은 유틸을 추가합니다. 참고: p95는 요청의 95%가 그 값 이하에 들어가는 지점입니다.

function percentile(values: number[], p: number) {
  const sorted = values.filter(v => v >= 0).sort((a, b) => a - b);
  if (!sorted.length) return 0;
  const idx = Math.floor((p / 100) * (sorted.length - 1));
  return sorted[idx];
}

function errorRate(values: number[]) {
  const total = values.length;
  const errors = values.filter(v => v < 0).length;
  return (errors / total) * 100;
}

그리고 main에 출력을 추가합니다:

const p95 = percentile(all, 95);
const p99 = percentile(all, 99);
const errRate = errorRate(all);

console.log(`Total: ${all.length}`);
console.log(`p95: ${p95} ms, p99: ${p99} ms`);
console.log(`Error rate: ${errRate.toFixed(2)}%`);

이제 로컬이나 스테이징에서 릴리스 전에 실행할 수 있는 최소한의 smoke‑load 스크립트를 얻었습니다. ChatGPT를 건드리지 않고, 토큰을 태우지도 않으면서 MCP에 집중할 수 있습니다.

ACP와 checkout은 어떻게 할까

마찬가지로 ACP 엔드포인트를 두드리는 helper callCreateCheckoutSession을 추가할 수 있습니다. 여기서는 실제 주문을 늘리지 않도록 결제의 테스트/샌드박스 모드를 사용해야 합니다. 전형적인 호출은 JSON 본문을 가진 일반 POST처럼 보일 것입니다:

async function callCreateCheckoutSession(productId: string) {
  const started = Date.now();
  const res = await fetch("http://localhost:3000/api/checkout/create", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ productId, test: true }),
  });
  const latencyMs = Date.now() - started;
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return latencyMs;
}

그런 다음 runVirtualUser에서 “검색 3회 → checkout 1회” 같은 패턴을 넣어, “검색은 많고 구매는 적은” 퍼널을 시뮬레이션할 수 있습니다.

5. 좀 더 진지한 도구: k6(하지만 간단하게)

Node 스크립트는 “최소 진입”으로 좋지만, 때로는 k6처럼 특화 도구를 쓰는 것이 편합니다. 시나리오는 JavaScript로 작성하고, 런타임은 Go 기반(빠름)입니다.

MCP를 위한 작은 k6 스크립트 예시:

// loadtest-mcp.js
import http from "k6/http";
import { check, sleep } from "k6";

export const options = {
  stages: [
    { duration: "30s", target: 30 },
    { duration: "2m", target: 30 },
  ],
};

export default function () {
  const payload = JSON.stringify({
    jsonrpc: "2.0",
    id: `search-${Math.random()}`,
    method: "tools/call",
    params: {
      toolName: "giftgenius.search_gifts",
      arguments: { occasion: "birthday", budget: 50 },
    },
  });

  const res = http.post(__ENV.MCP_URL, payload, {
    headers: { "Content-Type": "application/json" },
  });

  check(res, { "status is 200": (r) => r.status === 200 });
  sleep(1);
}

실행 명령:

MCP_URL=http://localhost:3000/api/mcp k6 run loadtest-mcp.js

k6p95/p99와 error rate를 자동으로 계산하고, 보기 좋은 리포트를 제공합니다 — 이후 Grafana 등으로 내보낼 수 있습니다.

이런 도구를 써도 목표는 동일합니다. 백만 RPS를 버티는 것이 아니라, 예상 피크의 5–10배에서도 시스템이 무너지지 않고 p95가 SLO 범위 안에 머무는지 확인하는 것입니다.

6. 부하 실행 중(및 후)에 무엇을 볼까

이미 메트릭과 SLO를 논의했으니, 이를 부하 컨텍스트에 “착지”시켜 보겠습니다.

첫째, 지연 시간(latency). search_gifts 같은 MCP 도구에 대해 “p95 < 2–3초” 같은 목표를 미리 세워 두었을 것입니다. smoke‑load 동안 p95/p99가 2–3배로 치솟지 않는지 봅니다. 이때 베이스라인과 비교하는 것이 중요합니다. 코드 변경 전 p95가 400ms였는데 이후 1500ms가 되었다면, 형식상 아직 SLO 안이라도 이미 고민해야 할 신호입니다.

둘째, error rate. 부하에서는 예상치 못한 것들이 자주 튀어나옵니다: DB 연결 풀 고갈, 외부 API의 429, 결제사 호출 타임아웃 등. 정상 부하에서는 error rate가 0에 가깝고, smoke‑load에서도 드문 실패만 허용될 뿐 5–10% 같은 수치는 절대 용납되지 않습니다.

셋째, 리소스 메트릭. CPU, 메모리, 때로는 열린 파일 디스크립터/연결 수 등. 인프라에 따라 달라지지만 핵심은 단순합니다: VU 30에서 CPU가 100%이고 GC가 절반의 시간을 잡아먹는 상황은 원하지 않습니다.

넷째, 웹훅. 커머스 시나리오에서는 주문의 최종 상태가 종종 결제 시스템의 웹훅을 성공적으로 처리하는지에 달려 있습니다. ACP 요청 속도뿐 아니라 “웹훅 도착 → 우리가 성공적으로 처리”까지의 지연도 보아야 합니다.

마지막으로, 로그. trace_id/checkout_session_id가 있는 구조화 로그는 부하 실행 후 가장 느리거나 실패한 요청 몇 개를 집어 MCP → 외부 API → ACP → 웹훅으로 이어지는 체인을 추적하게 해줍니다. 특히 부하에서 이상한 p99 꼬리를 볼 때 유용합니다.

7. 피드 데이터 품질: 구조에서 의미까지

부하에서 지연, 오류, 리소스가 모두 괜찮더라도, 데이터가 나쁘면 사용자 경험은 여전히 “부서질” 수 있습니다.

두 번째 큰 주제인 데이터로 넘어가겠습니다. GiftGenius 같은 커머스 앱에서 product feed(상품 피드)는 “어딘가의 파일”이 아니라 LLM과 에이전트를 위한 연료입니다. 피드가 쓰레기라면, 모델은 가격과 재고를 “지어내지” 않습니다.

피드 품질을 세 가지 층으로 생각하면 편합니다.

구조적 수준

기본적인 데이터 유효성입니다:

  • JSON이 올바르게 파싱된다.
  • 모든 필수 필드가 존재한다: id, name, price, currency, imageUrl, availability 등.
  • 값의 타입이 기대에 맞다: 가격 — 숫자, availability — enum, categories — 문자열 배열.
  • id 중복이 없다.

이 중 일부는 이미 피드에 대한 JSON Schema/Zod 스키마를 정의하면서 계약 테스트로 커버했을 것입니다. 이제 이 스키마를 실제 데이터 볼륨에 적용해야 합니다.

GiftGenius 피드 항목을 위한 간단한 Zod 스키마 예시:

import { z } from "zod";

export const giftItemSchema = z.object({
  id: z.string().min(1),
  name: z.string().min(3),
  description: z.string().optional(),
  price: z.number().positive(),
  currency: z.enum(["USD", "EUR", "GBP"]),
  imageUrl: z.string().url(),
  inStock: z.boolean(),
  tags: z.array(z.string()).default([]),
});

전체 피드 스키마는 z.array(giftItemSchema)처럼 간단합니다.

비즈니스 수준(시맨틱)

구조적으로는 유효해도, 비즈니스 관점에서는 말이 안 될 수 있습니다:

  • 고가 상품인데 가격이 0 또는 0.01.
  • 시장에 맞지 않는 통화(오직 EUR로만 판매되는데 USD).
  • inStock = true인데 마지막 업데이트가 반년 전.
  • 표준화 없이 1000가지나 되는 카테고리.

이 수준에서는 추가적인 검증과 “상식 규칙”을 더하는 것이 유용합니다. 예를 들어:

const businessRules = (item: GiftItem) => {
  const problems: string[] = [];

  if (item.price > 10000) {
    problems.push("의심스러울 만큼 높은 가격");
  }
  if (!item.inStock && item.tags.includes("bestseller")) {
    problems.push("베스트셀러인데 재고 없음");
  }
  return problems;
};

이런 검증은 야간 배치나 새 피드를 생성할 때 실행하도록 할 수 있습니다.

LLM 수준

모델은 매우 똑똑하지만, 나름의 “약점”이 있습니다:

  • HTML, 불필요한 태그, 기술적 텍스트가 잔뜩 섞인 설명.
  • locale 명시 없이 언어가 뒤섞임(피드의 절반은 러시아어, 절반은 영어 등).
  • “최고의 초특가 선물 지금 구매” 같은 과도한 SEO식 긴 이름.

이 수준에서는 데이터를 모델 친화적으로 만드는 것이 중요합니다:

  • HTML 태그를 제거하거나 plaintext로 정리.
  • 설명 언어를 정규화(최소한 locale을 명시).
  • 지나치게 긴 이름과 중복 정보를 잘라내기.

이 작업은 일부는 전처리 스크립트로 자동화하고, 일부는 피드를 채우는 팀과 기준을 합의할 수 있습니다.

8. 실습: GiftGenius용 피드 검증기

프로젝트에 간단한 스크립트 validateFeed.ts를 추가해, 피드 JSON을 읽고 Zod로 검증한 뒤 기본 품질 메트릭을 계산해 봅시다.

// scripts/validateFeed.ts
import { readFile } from "fs/promises";
import { giftItemSchema } from "../src/schema/giftItem";

async function main() {
  const raw = await readFile("data/gift-feed.json", "utf-8");
  const data = JSON.parse(raw);

  const items = giftItemSchema.array().parse(data);
  console.log(`총 상품 수: ${items.length}`);

  const missingImages = items.filter(i => !i.imageUrl).length;
  console.log(`이미지 없음: ${missingImages}`);
}

main().catch((e) => {
  console.error("Feed validation failed:", e);
  process.exit(1);
});

여기서는 MCP 서버와 동일한 계약을 사용합니다. 즉, 계약 테스트와 피드 검증이 하나의 스키마를 공유하므로, 불일치 가능성이 크게 줄어듭니다.

그다음 비즈니스 규칙 검증과 다음과 같은 메트릭을 추가할 수 있습니다:

  • 설명이 없는 상품 비율;
  • 의심스러울 정도로 낮거나 높은 가격의 상품 비율;
  • id 중복 개수 또는 name + price 중복 개수.

이 숫자들은 Prometheus, Datadog 등의 메트릭 시스템으로 전송해, 데이터 품질에 대한 별도의 SLO를 유지할 수 있습니다 — 코드에 SLO를 두는 것과 동일하게요.

9. 부하와 피드는 어떻게 연결되는가

겉보기에는 “성능”과 “데이터 품질”이 크게 관련 없어 보일 수 있습니다. 실제로는 꽤 밀접하게 얽혀 있습니다.

연결 고리 예:

  • 부하에서는 이전에 거의 보지 못한 “희귀” 로직 가지로 일부 요청이 흘러갑니다. 예를 들어, 특수한 할인 타입이나 비표준 shipping이 붙은 상품. 이 지점의 피드가 지저분하면 오류도, 성능 저하도(검증/예외/fallback 로직의 산더미) 함께 나타날 수 있습니다.
  • 피드가 매우 시끄럽다면(HTML이 잔뜩인 긴 설명, 무의미한 태그), MCP 서버는 더 많은 데이터를 끌어오고 직렬화해야 하므로, tool-call 처리 시간과 응답 크기에 직접적인 영향을 줍니다.
  • 커머스 영역에서 나쁜 피드는 “빈” checkout 시도가 많아지는 원인이 됩니다. 사용자가 고른 상품이 갑자기 품절인 경우처럼요. 이는 UX에도, ACP 메트릭(실패 intent 증가)에도 악영향을 줍니다.

이를 행렬처럼 바라보면 편합니다:

피드 문제 부하 시 증상 어디서 볼 것
가격/통화 불일치 ACP 오류, 거절된 결제 ACP 로그 + checkout SLO
상품 중복 이상한 추천 결과, 불필요한 호출 MCP 로그, UX 메트릭
이미지/설명 없음 모델이 “밋밋한” 추천을 생성 App 로그 + UX 피드백
설명에 HTML/노이즈 느린 직렬화, 큰 페이로드 MCP 지연 시간

부하 실행은 손전등 같은 역할을 합니다. 평소에는 잘 건드리지 않던 피드의 구간을 비춰 주어, 트래픽이 활성화되면 문제를 일으키는 지점을 드러냅니다.

10. GiftGenius 릴리스 프로세스에 녹여 넣기

프로세스 관점에서 위 내용은 “첫 프로덕션 전 한 번”으로 끝나서는 안 됩니다. 모듈 16(“프로덕션, 네트워크, 스케일링”)과 17(“관측 가능성과 품질”)의 커리큘럼에서는 이를 정기적인 릴리스 체크리스트의 일부로 녹여 두었습니다. 릴리스 전 unit/contract/E2E만 돌리는 것이 아니라, 짧은 smoke‑load와 피드 검증도 함께 수행합니다.

배포 전 합리적인 최소 파이프라인:

  1. Unit + contract + 통합 테스트가 모두 그린.
  2. 중요 코드(검색 로직, DB 연동, checkout)가 변경되었다면 스테이징에서 MCP/ACP 대상 짧은 smoke‑load.
  3. 피드 검증기가 오류 없이 완료되고, 피드의 기본 메트릭(깨진 레코드 수, 이미지 없는 비율 등)이 허용 범위 내.
  4. 새 엔드포인트와 SLO를 반영해 대시보드와 알림을 업데이트.
  5. 실패 시 롤백 플랜 준비: 기능 플래그로 비활성화하거나 빌드 롤백.

이렇게 하면 GiftGenius는 “DevDay 데모”를 넘어 Store와 트래픽 급증에서도 버틸 준비가 된 서비스가 됩니다.

11. 부하 테스트와 피드 검증에서 흔한 실수

오류 №1: 자신의 백엔드가 아니라 “ChatGPT를 통한” 부하 테스트.
“현실 그대로를 테스트한다”라며 ChatGPT UI를 통해 스크립트를 돌리는 경우가 있습니다. 결과적으로 OpenAI 한계에 부딪히고, 토큰을 소모하며, 매우 시끄러운 결과를 얻게 됩니다. 반면 MCP/ACP 문제는 /mcp/api/checkout에 직접 쏘았다면 100배는 더 싸게 잡을 수 있었습니다.

오류 №2: 평균 응답 시간만 본다.
“우리 평균 지연이 500ms라서 다 좋아요” — 그런데 p95가 5초인 건 왜 잊을까요. 이미 SLO 주제에서 논의했듯, 실제 UX를 좌우하는 것은 분포의 꼬리(p95/p99)입니다. 부하에서 평균은 종종 멀쩡해 보이지만 꼬리는 두세 배로 자랍니다.

오류 №3: 실용적인 smoke‑load 대신 “엔터프라이즈급 부하”를 하려 든다.
수개월에 걸쳐 수만 사용자를 흉내 내는 복잡한 스탠드를 만드는 것은 GiftGenius 수준의 ChatGPT App에는 거의 불필요합니다. 이해하기 쉬운 메트릭으로 50–100 VU의 간단하지만 정기적인 smoke‑load가 훨씬 유익합니다.

오류 №4: 비현실적인 부하 시나리오.
스크립트가 사용자/언어/상품 타입 변이 없이 똑같은 요청만 보내고, ACP와 웹훅은 전혀 건드리지 않습니다. 그 결과 뜨거운 해피 패스만 테스트하고, 시스템의 “모서리”는 여전히 어둠 속에 남습니다. 최소한 단순하지만 그럴싸한 플로우를 모델링하세요: 다른 예산, 다른 관심사, 일부는 checkout까지 가고 일부는 가지 않는 식으로.

오류 №5: 피드를 “눈대중”으로만 보거나 프로덕션에서만 확인.
피드를 모아 프로덕션에 내보낸 뒤, 모델의 이상한 추천을 보고 머리를 긁적입니다. 간단한 Zod/JSON Schema 스크립트만 있었어도 1분 만에 “10%는 이미지 없음, 5%는 가격 0, 3%는 통화가 XXX” 같은 사실을 보여줬을 겁니다. 자동 피드 검증의 부재는 커머스 앱에서 가장 흔한 부끄러움의 원인입니다.

오류 №6: 나쁜 피드에서도 LLM이 “다 알아서 할 것”이라는 기대.
모델이 많은 것을 해내긴 하지만, 올바른 가격이나 재고를 만들어내지는 않습니다. 같은 상품이 피드에 서로 다른 가격/재고로 등장하면, 에이전트는 환각과 불일치한 사용자 경험을 모두 초래할 수 있습니다. 데이터 청결에 대한 책임은 모델이 아니라 여러분에게 있습니다.

오류 №7: 피드 메트릭과 전체 SLO 사이의 연결 부재.
MCP와 ACP가 아무리 빨라도, 피드의 30%가 “깨져” 있다면 사용자 경험은 끔찍합니다. 종종 팀은 기술적 SLO(지연, error rate)만 추적하고 데이터 품질 SLO(유효 SKU 최소 비율, 중복 최대치 등)는 무시합니다. 그 결과 “숫자는 좋아 보이는데” 체감은 좋지 않은 상황이 생깁니다.

오류 №8: 준비 없이 바로 프로덕션에서 부하 테스트 실행.
어떤 이는 금요일 저녁 “보자, k6로 프로덕션 MCP를 금방 돌려보자”라고 합니다. 최선의 경우 실제 메트릭을 흐리고 on‑call 엔지니어를 트래픽 급증으로 당황하게 만들고, 최악의 경우 외부 API나 결제사의 rate‑limit에 걸립니다. 항상 첫 시나리오는 스테이징에서 돌리고, 프로덕션 테스트가 필요하면 창구/공지 등 절차를 갖추어 의도적으로 진행하세요.

1
설문조사/퀴즈
관측 가능성과 품질, 레벨 17, 레슨 4
사용 불가능
관측 가능성과 품질
관측 가능성과 품질
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION