1. 왜 로컬 디버그에 대한 별도의 강의가 필요한가
이전 모듈에서 이미 Apps SDK와 MCP 스택이 어떻게 생겼는지 보았습니다. 이제 왜 로컬 디버그만을 다루는 별도의 강의가 필요한지 이야기해 봅시다.
많은 분들이 이렇게 합니다: “그냥 ChatGPT를 열고 ‘내 App을 써’라고 쓰고, 그다음엔 뭐라고 하는지 보기. 안 되면 감으로 코드를 고치기.” 이는 서버 로그를 한 번도 보지 않고 브라우저의 HTML 페이지만 보며 백엔드를 고치는 것과 비슷합니다.
ChatGPT Apps는 특히 “마법”으로 흐르기 쉽습니다. GPT가 도구 호출 여부를 스스로 결정하고, 자체적인 오류 처리 로직도 있습니다. 내부에서 무슨 일이 일어나는지 보지 못하면 디버그는 북치고 춤추는 주술이 되어 버립니다.
우리의 목표: 이를 정상적인 엔지니어링 프로세스로 바꾸는 것입니다:
- Next/MCP 로그를 어디서 보는지 압니다;
- MCP 서버를 인스펙터로 수동 호출할 수 있습니다;
- Dev Mode가 정확히 무엇을 검사하는지 이해하고, ChatGPT가 여러분의 서버에 실제로 접속할 수 있는지 확인할 수 있습니다.
그리고 가장 중요한 것: “GPT 추측 디버그”를 멈추고 먼저 스택의 하위 레벨—서버와 프로토콜—을 점검한 뒤 UI와 모델 동작을 확인하기 시작합니다.
2. 멘탈 모델: 디버그의 세 가지 레벨
혼돈에 빠지지 않도록, 디버그를 세 가지 레벨 관점에서 생각하기로 합시다. 일종의 “레이어드 케이크”입니다:
| 레벨 | 무엇이 있는가 | 전형적 증상 | 디버그 도구 |
|---|---|---|---|
| UI(위젯) | React 컴포넌트, 상태, window.openai | 위젯이 비어 있거나 회색, 렌더링 이상, 버튼 동작 안 함 | 브라우저 DevTools |
| 백엔드 / MCP‑서버 | 툴, DB/API 접근 | 500 오류, “툴 실행 실패”, 이상한 데이터 | 서버 로그, MCP Inspector |
| MCP 프로토콜 | JSON‑RPC, tools/list, tools/call, 스키마 | GPT가 “도구를 호출할 수 없었다”고 말함, invalid params | 인스펙터 + 요청 로그 |
두 번째 레벨에서는 MCP 서버 자체(툴, DB, API)가 무엇을 하는지가 관심사이고, 세 번째 레벨에서는 “배선”과 MCP 메시지 형식(JSON‑RPC, 스키마 등)에 집중합니다.
이 세 가지가 이 강의와 디버그 커리큘럼의 뼈대입니다.
요청 흐름을 한눈에 보면 다음과 같습니다:
sequenceDiagram
participant User as 사용자
participant ChatGPT as ChatGPT (Dev Mode)
participant Tunnel as 터널 (ngrok/CF)
participant Next as Next.js + MCP
User->>ChatGPT: "50달러 이하 선물 추천해 줘"
ChatGPT->>Next: tools/call search_gifts (터널을 통해)
Next->>Next: MCP 툴 호출, DB/API 접근
Next-->>ChatGPT: JSON-RPC result + ToolOutput
ChatGPT-->>User: 응답 + 위젯 렌더링
어디에서든 깨질 수 있습니다: 터널, 엔드포인트, MCP 로직, JSON 스키마, React 위젯. 디버그의 핵심 과제는 정확히 어떤 레이어에서 문제가 발생하는지 파악하는 것이지, 곧장 모든 것을 다시 쓰는 것이 아닙니다.
3. Next.js와 MCP 로그: 디버그의 기본
가장 지루하면서도 가장 유용한 것—로그부터 시작합시다.
로컬 개발 시 로그는 어디에 있는가
Next.js 기반 Apps SDK의 표준 템플릿에서 MCP 서버는 보통 API 라우트(/api/mcp 등)로 감쌉니다. npm run dev를 실행하면 하나의 터미널에서:
- Next.js 개발 서버가 뜨고;
- MCP 엔드포인트 핸들러가 tools/list, tools/call 같은 JSON‑RPC 요청을 받고;
- console.log/console.error로 모든 이벤트가 출력됩니다.
MCP를 별도 프로세스로 분리했다면 터미널이 하나 더 있겠지만, 아이디어는 같습니다. 중요한 것은 콘솔에서 모든 흥미로운 내용을 볼 수 있다는 점입니다.
다음을 구분하는 것이 중요합니다:
- 빌드/시작 오류 — next dev가 뜨지 않거나 TypeScript가 크래시, 잘못된 import 등;
- 실행 중 오류 — 전체는 기동되었지만 특정 /api/mcp 요청에서 툴이 실패하는 경우.
Next.js는 개발 모드에서 런타임 오류를 오버레이로 보기 좋게 보여 주고, 콘솔에 스택 트레이스도 남겨 줍니다.
MCP 서버에서 무엇을 로깅할 것인가
MCP는 JSON‑RPC 프로토콜을 사용하지만, 디버그를 위해 모든 JSON을 전부 찍을 필요는 없습니다. 짧지만 구조화된 로그가 훨씬 유용합니다.
좋은 MCP 로그 관행은 최소한 다음을 남기는 것입니다: timestamp, request_id/traceId, 툴 이름, 매개변수(비식별화), 상태(ok/error), 실행 시간.
GiftGenius용 가장 단순한 logger.ts는 다음과 같을 수 있습니다:
// src/lib/logger.ts
export function logToolEvent(
phase: "start" | "end" | "error",
data: Record<string, unknown>
) {
const ts = new Date().toISOString();
console.log(JSON.stringify({ ts, phase, ...data }));
}
툴 핸들러에서는 이렇게 사용합니다:
// src/mcp/tools/searchGifts.ts
import { logToolEvent } from "@/lib/logger";
export async function searchGiftsTool(args: { q: string }) {
const traceId = crypto.randomUUID();
logToolEvent("start", { tool: "search_gifts", traceId, args });
try {
// ... 실제 선물 검색 ...
const results = []; // 스텁
logToolEvent("end", { tool: "search_gifts", traceId, count: results.length });
return results;
} catch (err) {
logToolEvent("error", { tool: "search_gifts", traceId, error: String(err) });
throw err;
}
}
두 가지 중요 포인트가 있습니다.
첫째, 로그에 전체 e‑mail, 전화번호, 카드번호, 토큰을 남기지 마세요. 보기 나쁠 뿐 아니라 MCP의 기본 보안 관행에도 어긋납니다.
둘째, traceId는 최고의 친구입니다. Next.js 로그와 MCP 로그를 함께 볼 때, 특정 tools/call 요청, 해당 React 렌더, 위젯의 네트워크 로그를 이 ID로 쉽게 연결할 수 있습니다.
로그로 어디서 실패했는지 파악하기
터미널에서 logToolEvent가 찍는 JSON 줄들을 봅니다. 전형적 시나리오:
- phase: "start"와 tool: "search_gifts"가 도착;
- phase: "end"는 없고, phase: "error"와 스택 트레이스가 있음;
- 즉, 툴 로직까지는 진입했지만 내부에서 무언가 깨짐 — 예: 외부 API 호출, 파싱, DB 작업 등.
반대로 해당 툴 이름의 로그 자체가 없다면 — 요청이 툴까지도 도달하지 못한 것입니다. 그러면 스택 상위로 올라가 터널, /mcp 엔드포인트, tools/call JSON 요청을 확인합니다.
4. MCP Inspector: ChatGPT 없이 MCP만으로 디버깅
로그가 눈이라면, MCP Inspector(또는 MCPJam Inspector)는 현미경입니다.
MCP Inspector란? 왜 필요한가
MCP 모듈에서 이미 Inspector를 붙여 “Hello, MCP” 서버를 확인해 봤습니다. 여기서는 이것을 주 디버그 도구로 사용합니다: 먼저 MCP가 자체적으로 잘 동작하는지 확인하고, 그다음 Dev Mode와 UI를 봅니다.
Inspector는 별도의 애플리케이션(대개 웹 UI + CLI)로, MCP 클라이언트 역할을 합니다. HTTP/SSE 또는 stdin/stdout으로 서버에 연결해 tools/list, tools/call을 수행하고, 원시 JSON 메시지, 핸드셰이크, 툴 목록, 리소스 등을 보여 줍니다.
핵심 아이디어: ChatGPT를 식에서 제거하는 것입니다. 툴이 동작하지 않으면 GPT를 탓하기 전에 서버가 살아 있는지, 프로토콜과 스키마가 올바른지 먼저 확인해야 합니다.
Inspector 사용 미니 플로우
전형적인 로컬 디버그 플로우는 다음과 같습니다:
- npm run dev를 실행해 Next.js + MCP 엔드포인트를 띄웁니다.
- MCP Inspector를 실행합니다. 예:
npx @modelcontextprotocol/inspector
(구체 명령은 사용하는 도구에 따라 다를 수 있습니다.)
- Inspector에서 MCP 엔드포인트 URL을 지정합니다. 예: http://localhost:3000/api/mcp(또는 터널을 함께 검증하려면 HTTPS 터널).
- 핸드셰이크가 통과했는지 확인합니다: 서버가 지원하는 capabilities, 툴 목록, 리소스 등을 응답해야 합니다.
- 관심 있는 툴을 수동 호출합니다: search_gifts를 선택하고, 인자 {"q": "30세 이하 여성을 위해"}를 입력하고 “Call tool”을 눌러 다음을 확인합니다:
- 응답이 왔는지;
- JSON‑RPC 또는 MCP 오류가 반환되지 않았는지;
- 해당 호출에 대해 서버 로그가 무엇을 기록했는지.
Inspector에서 이미 실패한다면 ChatGPT를 열 필요도 없습니다. MCP 서버부터 고치세요.
Inspector에서는 모두 정상인데 ChatGPT가 계속 불평한다면 — 문제는 더 위에 있습니다: Dev Mode URL, 인증, 모델의 행위 등.
의도적으로 툴을 망가뜨리는 예
우리의 search_gifts를 일부러 이렇게 망가뜨려 보겠습니다:
export async function searchGiftsTool(args: { q: string }) {
if (args.q === "고장나") {
throw new Error("디버그 시연을 위한 학습용 오류");
}
// ... 정상 로직 ...
return [];
}
그다음:
- Inspector에서 search_gifts를 {"q": "고장나"} 인자로 호출합니다.
- 로그에서 phase: "error"와 스택 트레이스를 확인합니다.
- MCP 서버가 오류를 정직하게 반환함을 확인합니다.
그 후 ChatGPT Dev Mode에 연결하고 모델에게 “'고장나'라는 단어가 들어간 선물을 추천해 줘”라고 요청하면, 모델은 툴을 호출하려다 실패 메시지(예: “I encountered an error running the tool”)를 사용자에게 보여 줄 것입니다. 즉, 오류는 모델 때문이 아니라 여러분이 던진 명시적 예외 때문에 발생한다는 점이 분명해집니다.
이런 연습은 사고 훈련에 좋습니다. 비즈니스 오류(우리가 Error를 직접 던짐)와 프로토콜 오류(JSON을 깨뜨리거나, 잘못된 툴 이름 등)를 명확히 구분하게 됩니다.
5. 위젯 디버그: DevTools, 상태, “디버그 배너”
MCP 서버가 어느 정도 명확해졌다면, 이제 프런트엔드—Apps SDK 위젯으로 갑시다.
위젯 오류는 어디서 어떻게 볼까
여러분의 위젯은 ChatGPT 내부의 iframe 샌드박스에서 렌더링됩니다. 좋은 소식은: 이 iframe에도 동일한 브라우저 DevTools가 있다는 것입니다.
미니 절차:
- 브라우저(Chrome/Edge/Firefox)에서 ChatGPT를 엽니다.
- DevTools를 엽니다(일반적으로 F12 또는 Ctrl+Shift+I).
- Console 탭에서 위젯이 있는 프레임 컨텍스트를 선택합니다(종종 도메인이 web-sandbox.oaiusercontent.com입니다).
- 챗을 새로고침/메시지를 전송해 GPT가 여러분의 App을 보여 주도록 합니다.
위젯이 다음과 같다면:
- 아예 나타나지 않거나;
- 회색/빈 화면으로 보이거나;
- 콘솔에 빨간 오류를 표시한다면
— 이는 거의 확실히 React 코드 문제입니다: 접근 불가능한 속성, 잘못된 import, 잘못된 훅 등.
Network 탭도 유용합니다. 여기에서 다음을 볼 수 있습니다:
- 앱의 JS 번들 로드(만약 404/500이라면 dev 서버/터널 쪽 문제);
- 위젯이 window.fetch로 외부에 보내는 요청과 4xx/5xx 응답.
아주 간단한 디버그 배너
Dev Mode에서 환경과 빌드 버전을 보여 주는 작은 “디버그 배너”를 위젯의 루트 컴포넌트에 추가하는 것이 매우 편리합니다.
예:
// src/components/DebugBanner.tsx
export function DebugBanner() {
if (process.env.NODE_ENV !== "development") return null;
return (
<div style={{ padding: 4, background: "#222", color: "#0f0", fontSize: 10 }}>
ENV: dev | build: local | {new Date().toLocaleTimeString()}
</div>
);
}
루트 위젯 컴포넌트에서 사용:
// src/app/widget/page.tsx
import { DebugBanner } from "@/components/DebugBanner";
export default function GiftGeniusWidget() {
return (
<div>
<DebugBanner />
{/* 나머지 선물 검색 UI */}
</div>
);
}
ChatGPT를 열고 App을 실행했는데 배너가 보이지 않는다면 — 여러분의 JS가 브라우저에 도달하지 않았다는 뜻입니다: 빌드 오류, 엔드포인트 문제, 또는 위젯이 MCP 서버에 등록되지 않았을 수 있습니다.
로컬 상태와 오류 처리
여러분의 위젯은 이미 다양한 상태(로딩, 성공, 오류)를 표시할 수 있어야 합니다. 아니라면 지금이 추가할 때입니다.
미니 패턴:
const [status, setStatus] = useState<"idle"|"loading"|"error"|"success">("idle");
async function handleSearch(query: string) {
try {
setStatus("loading");
// window.openai.callTool 또는 Apps SDK 훅을 통해 MCP 툴 호출
setStatus("success");
} catch (e) {
console.error("Search failed", e);
setStatus("error");
}
}
JSX에서:
{status === "error" && (
<div style={{ color: "red" }}>문제가 발생했습니다. 다시 시도해 주세요.</div>
)}
디버그를 위해 중요한 점:
- 예외를 삼키지 마세요(그렇지 않으면 콘솔은 조용하고 UI만 “멈춘” 것처럼 보입니다);
- UI에서 오류를 명시적으로 반영하세요. 그렇지 않으면 사용자는 App이 죽었다고 느낍니다.
6. 디버그의 일부로서 Dev Mode: 무엇을 하는지, 그리고 억울한 오해를 줄이는 법
이제 ChatGPT Dev Mode를 그림에 넣어 봅시다. 지금까지는 여러분의 코드만 봤습니다. 그런데 때로는 로컬에서도 잘 동작하고, Inspector에서도 완벽한데, ChatGPT는 여전히 “Error talking to [AppName]”이라고 하거나 아예 여러분의 App을 제안하지 않습니다.
Dev Mode는 무엇을 하는가
Dev Mode는 ChatGPT에서 다음을 할 수 있는 모드입니다:
- 여러분의 App을 만들고 수정;
- MCP 서버 엔드포인트 지정(보통 https://여러분의-도메인/mcp 또는 /api/mcp);
- 스토어에 퍼블리시하지 않고도 매니페스트와 메타데이터를 빠르게 갱신.
디버그 관점에서 Dev Mode는 하나의 구성 계층일 뿐입니다:
- URL이 잘못되어 있거나;
- 끝에 /mcp를 빼먹었거나;
- 터널 도메인이 바뀌었는데 설정을 갱신하지 않았다면
— ChatGPT는 여러분의 서버에 도달하지 못합니다.
Dev Mode에서 자주 깨지는 시나리오
클래식:
- https://abcd.ngrok.io 터널을 띄우고 Dev Mode에 등록해 모두 잘 동작.
- 다음 날 ngrok을 재시작했더니 https://efgh.ngrok.io를 받음.
- Dev Mode에는 여전히 https://abcd.ngrok.io/mcp.
- ChatGPT가 “Error talking to GiftGenius”라고 표시.
이때 MCP Inspector를 http://localhost:3000/api/mcp에 붙이면 모든 게 정상으로 보일 수 있습니다. MCP는 살아 있지만 ChatGPT가 엉뚱한 곳을 보고 있는 것입니다.
해결: Dev Mode 설정으로 들어가 URL을 갱신하고, 끝에 /mcp를 잊지 마세요.
Dev Mode vs Store
이 강의에서는 Dev Mode만 다룹니다 — 여러분의 샌드박스죠. 여기서는 URL을 자주 바꾸고 터널을 재연결하고 툴 스키마를 고치는 것이 정상입니다.
나중에 Store로 가면 엔드포인트가 더 엄격히 고정되고, 이런 요령은 좋은 생각이 아닙니다. 하지만 Store까지는 아직 몇 모듈 남았으니, 지금은 Dev Mode에서 마음 놓고 부수고 고쳐 봅시다.
7. 미니 디버깅 알고리즘: “아무것도 안 된다”일 때
이제 모든 것을 실전 알고리즘으로 묶겠습니다. 본질적으로는 강의 초반의 세 레벨 디버그를 순서로 정리한 것입니다.
ChatGPT를 열고 GiftGenius를 선택한 뒤 “친구 기크를 위해 30$ 이하의 선물을 추천해 줘”라고 요청했는데:
- GPT가 App에 대해 아무 말도 하지 않거나;
- “Error talking to GiftGenius”라고 쓰거나;
- 빈/회색 위젯이 열린다면.
어떻게 좌절하지 않을까요?
1단계 (MCP/서버 레벨): Inspector와 로그로 MCP 확인
우선 GPT와 UI는 무시합니다. 서버만 봅니다.
- npm run dev가 실행 중이며 엔드포인트(/api/mcp)가 응답하는지 확인합니다.
- MCP Inspector를 http://localhost:3000/api/mcp 또는 터널에 연결합니다.
- 핸드셰이크를 점검합니다 — 툴 목록이 보여야 합니다.
- GPT가 호출할 것으로 예상되는 동일한 툴(예: search_gifts)을 유사한 인자로 수동 호출합니다.
여기서부터 이미 실패한다면 MCP를 고치세요: 스키마, 비즈니스 로직, 네트워크 호출. 무엇이 깨지는지 파악하려면 로그와 traceId를 사용하세요.
2단계 (프로토콜/Dev Mode 레벨): Dev Mode와 URL 확인
Inspector에서는 완벽한데 ChatGPT가 여전히 여러분의 App을 보지 못하거나 연결 문제를 말한다면:
- 해당 App의 Dev Mode 설정을 엽니다.
- MCP용으로 지정된 URL이 무엇인지 확인합니다.
- 실제로 서버/터널이 리슨하는 주소와 일치하는지 대조합니다(서버가 요구한다면 끝에 /mcp가 있는지도 확인).
문제는 종종 여기 있습니다.
3단계 (UI 레벨): DevTools로 위젯 확인
ChatGPT가 툴을 정상 호출하는 것처럼 보이는데(MCP 로그에서 확인), 위젯이 이상하게 동작한다면:
- ChatGPT 페이지에서 브라우저 DevTools를 엽니다.
- Console 탭에서 위젯의 iframe 컨텍스트를 선택합니다.
- JS 오류를 확인합니다.
- Network 탭에서 다음을 확인합니다:
- 위젯 JS 번들이 404/500 없이 로드되는지;
- fetch/window.openai.fetch로 보내는 추가 요청이 의미 있는 응답을 반환하는지.
동시에 DebugBanner를 보세요: 나타나지 않는다면 React 트리까지 도달하지 못한 것입니다.
4단계. Dev Mode를 이용해 버그 리포트를 재현
동료/사용자로부터 버그 리포트를 받았다면, 문제가 발생한 정확한 프롬프트를 보존하려 노력하세요. Dev Mode에서는 시나리오를 매우 빠르게 재현할 수 있습니다:
- npm run dev를 실행하고 터널을 띄웁니다.
- Dev Mode에서 App을 선택합니다.
- 문제가 되는 프롬프트를 붙여 넣습니다.
- 동시에:
- MCP로 어떤 JSON 요청이 들어오는지 로그로 확인하고;
- 필요하다면 Inspector에서 동일한 인자로 tools/call을 반복합니다.
이렇게 하면 “가끔 안 된다”를 재현 가능한 시나리오로 바꿀 수 있습니다.
8. 디버그를 편하게 해 주는 작은 코드 팁
내용을 정리하며, GiftGenius 앱에 몇 가지 유용한 코드를 더해 봅시다.
환경 구성과 로그 레벨
서버 구성 어딘가에 MCP 엔드포인트와 로그 레벨을 명시해 두면 편합니다:
// src/config.ts
export const config = {
mcpEndpoint:
process.env.NODE_ENV === "development"
? "http://localhost:3000/api/mcp" // 터널이 이 주소를 노출합니다
: "https://api.giftgenius.com/api/mcp",
logLevel: process.env.NODE_ENV === "development" ? "DEBUG" : "ERROR",
};
그리고 logToolEvent에서 logLevel을 고려해 프로덕션에서는 불필요한 로그를 줄일 수 있습니다.
MCP의 구조화된 오류 로깅
툴 처리 시 예상 가능한 오류는 잡아서 이해 가능한 메시지로 반환하고, 모든 것을 throw로 던지지 않도록 노력하세요:
export async function searchGiftsTool(args: { q: string }) {
const traceId = crypto.randomUUID();
logToolEvent("start", { tool: "search_gifts", traceId, args });
try {
// ... 정상 코드 ...
return { content: [{ type: "text", text: "선물 3개를 찾았습니다" }] };
} catch (err) {
logToolEvent("error", { tool: "search_gifts", traceId, error: String(err) });
return {
content: [{ type: "text", text: "선물 검색 오류입니다. 나중에 다시 시도해 주세요." }],
isError: true,
};
}
}
이렇게 하면 ChatGPT가 결과에 isError가 표시된 것을 인지해 사용자에게 문제를 올바르게 전달할 수 있고, 여러분은 로그에서 무슨 일이 있었는지 명확히 볼 수 있습니다.
9. 로컬 디버그에서 흔한 실수 — ChatGPT App
실수 №1: 서버/인스펙터가 아니라 “GPT만 보고” 디버그하기.
모델이 무엇을 답하는지만 보고 버그가 어디에 있는지 “맞추고” 싶은 유혹이 큽니다. 하지만 모델은 최상층입니다. MCP 서버가(Inspector로, 수동으로) 자체적으로 동작하지 않는다면 GPT에게 기적을 기대할 수 없습니다. 먼저 MCP를 안정화한 뒤 ChatGPT를 연결하세요.
실수 №2: 로그를 아예 안 보거나, 전부 다 찍기.
로그가 없으면 완전한 맹목 상태입니다: 어떤 툴이 어떤 인자로 호출됐고 어떻게 끝났는지 모릅니다. 과도한 로깅은 반대로 콘솔을 의미 없는 문자열 “매트릭스”로 만듭니다. tool, args(비식별), traceId, status, 실행 시간을 담은 간결하고 구조화된 로그가 가장 좋습니다.
실수 №3: 로그에 민감 정보를 저장.
토큰, 전체 e‑mail, 카드번호를 로깅하는 것은 보안/정책 측면에서 모두 나쁜 관행입니다. 디버그에 진짜 필요한 정보만 로그에 남기고, 개인 데이터는 마스킹하거나 기록하지 마세요.
실수 №4: 모든 것을 Dev Mode 탓으로 돌리기.
Dev Mode는 종종 희생양이 됩니다: “OpenAI가 뭔가 망가뜨렸어.” 실제로는 터널 재시작 후 URL을 갱신하지 않았거나, 경로를 잘못 지정(/ 대신 /mcp)한 경우가 매우 잦습니다. 지원팀에 연락하기 전에 Dev Mode 설정에서 엔드포인트가 서버의 실제 주소와 일치하는지 확인하세요.
실수 №5: DevTools와 위젯 오류를 무시.
빈/회색 위젯은 거의 항상 클라이언트 측 JavaScript 오류를 의미합니다. MCP 로그만 보고 ChatGPT의 DevTools를 열지 않으면 그림의 절반만 보는 셈입니다. 자동으로 F12를 눌러 Console/Network를 확인하는 습관은 엄청난 시간을 절약합니다.
실수 №6: “마법의 지연”으로 버그를 “고치려” 하기.
때때로 setTimeout이나 Thread.sleep 스타일의 지연을 넣어 “모든 게 로드될 시간을 벌기”를 시도합니다. 하지만 MCP/Next/React 세계에서는 거의 항상 잘못된 처방입니다: 문제는 대개 스키마, 잘못된 엔드포인트, 코드 오류이지 “서버가 늦었다”가 아닙니다. (Inspector → Dev Mode → 위젯) 어디에서 단절되는지 이해하는 편이 지연으로 덮어 버리는 것보다 훨씬 낫습니다.
실수 №7: 로컬에서 확인도 안 하고 Vercel에 배포.
“빨리 프로덕션에”라는 마음은 이해하지만, 망가진 MCP를 Vercel에 올리는 것은 문제를 로컬과 프로덕션, 두 겹으로 만드는 가장 좋은 방법입니다. 이 모듈의 원칙은 명확합니다: 먼저 MCP Jam/Inspector → 모두 정상, Dev Mode → 기본 시나리오 정상. 그리고 나서 배포하세요.
GO TO FULL VERSION