이번 글에서는 MCP 툴 없이 직접 모델과 통신한 구현과 MCP 툴 기반 구조를 나란히 비교해보려 합니다.
두 방식 모두 질문 → SQL 생성 → 실행 → 요약이라는 흐름은 같지만, 구현 철학과 역할 분담 구조가 완전히 다릅니다.
1. 직접 모델 호출 방식 (비-MCP 방식)
먼저, 모델을 직접 호출해 SQL을 만들고, 그 결과를 요약하는 전통적인 접근입니다.
const result = await model.generateContent(prompt);
const text = (await result.response.text()).trim();
그리고 결과 rows를 직접 넣어서 요약 프롬프트를 또 호출하죠.
const prompt = `
질문: ${question}
결과: ${JSON.stringify(rows)}
→ 요약해줘
`;
const summary = (await model.generateContent(prompt)).response.text();
이 구조의 특징은:
- 모델에게 질문과 함께 컨텍스트를 주입
- 직접적인 요청 흐름
- 개발자가 모든 흐름을 설계함
2. MCP 툴 기반 구조
이번엔 MCP 툴 기반 구조입니다. 모델에게 툴 목록을 미리 등록해두고, 질문이 오면 모델이 스스로 "어떤 툴을 어떤 순서로 호출할지" 결정하도록 합니다.
MCP 방식에서는 이런 3개의 툴이 등록되어 있습니다:
🔧 1) generate-sql
server.tool(
'generate-sql',
{ properties: { question, tables } },
async (args) => {
const prompt = `질문: ${args.question}
테이블: ${args.tables.join(', ')}`;
const result = await model.generateContent(prompt);
return result.response.text();
}
);
🔧 2) execute-sql
server.tool(
'execute-sql',
{ properties: { sql: { type: 'string' } } },
async (args) => {
const result = await pool.query(args.sql);
return JSON.stringify(result.rows);
}
);
🔧 3) summarize-sql-result
server.tool(
'summarize-sql-result',
{ properties: { sql, rows } },
async (args) => {
const prompt = `질문 결과 요약:
SQL: ${args.sql}
데이터: ${JSON.stringify(args.rows)}`;
const result = await model.generateContent(prompt);
return result.response.text();
}
);
각 툴은 독립적으로 실행되며, 모델이 "연결 순서"를 판단하여 generate → execute → summarize
흐름을 조립합니다.
💡 동일한 기능을 직접 호출 방식으로 구현하면?
MCP 없이 구현한 코드에서는 아래처럼 3개의 함수를 직접 호출합니다:
📦 1) SQL 생성
async function generateSQL(question, tables) {
const prompt = `질문: ${question}
테이블: ${tables.join(', ')}`;
const result = await model.generateContent(prompt);
return result.response.text();
}
📦 2) SQL 실행
const rows = await pool.query(sql);
📦 3) 결과 요약
async function generateSummary(question, rows) {
const prompt = `질문: ${question}
데이터: ${JSON.stringify(rows)}`;
const result = await model.generateContent(prompt);
return result.response.text();
}
결론적으로 MCP 방식은 동일한 함수 단위를 툴로 감싸서 등록해두고, 모델이 필요한 순서로 호출하게 만든 구조입니다.
예: 등록된 MCP 툴 목록
generate-sql
: 자연어 → SQLexecute-sql
: SQL 실행summarize-sql-result
: 결과 요약
const parsedSteps = JSON.parse(await model.generateContent(prompt));
for (const step of parsedSteps) {
const toolResult = await server.callTool(step.tool, step.args);
}
이 구조는:
- 툴을 기반으로 설계됨
- 모델이 실행 순서를 조립함
- 서버는 단순히 툴 실행자 역할
구조적 비교
항목 | 직접 모델 호출 방식 | MCP 툴 기반 구조 |
---|---|---|
흐름 설계 | 개발자가 모두 설계 | 모델이 조립 |
확장성 | 프롬프트마다 추가 구현 필요 | 툴만 추가하면 됨 |
복잡도 | 처음은 단순하나 점점 커짐 | 초반 설계가 필요하지만 구조는 깔끔 |
모델 의존도 | 단발성 호출 중심 | 연속된 흐름도 모델이 주도 |
실제로 구현해보니
기능적인 결과는 거의 같습니다. 질문하면 SQL 생성되고, 실행되고, 요약도 됩니다. 사용자 입장에서는 두 방식 차이를 못 느낄 정도죠.
하지만 서버 입장에서 느껴지는 구조적 차이는 꽤 큽니다.
- 비-MCP는 일회성 처리가 편하고 빠름
- MCP는 구조를 한번 만들면 계속 재사용, 확장이 쉬움
또한 툴 단위로 분리해두면, 각 도구의 로깅, 테스트, 교체가 훨씬 유리해집니다.
마치며
두 가지 구조를 비교해보며 느낀 점은:
“작고 단순한 프로젝트는 직접 호출이 빠르지만, 복잡해질수록 MCP 기반이 구조적으로 더 낫다.”
긴 글 읽어 주셔서 감사합니다.
그리고 지금까지 소스 공개합니다.
REST API 기준
https://github.com/pm2makeq/chatbot_restapi
GitHub - pm2makeq/chatbot_restapi: restapi chatbot
restapi chatbot. Contribute to pm2makeq/chatbot_restapi development by creating an account on GitHub.
github.com
MCP 기준
https://github.com/pm2makeq/mcp-project
GitHub - pm2makeq/mcp-project
Contribute to pm2makeq/mcp-project development by creating an account on GitHub.
github.com
전체글
'프로그램 > AI' 카테고리의 다른 글
꾸역 꾸역 일러스트레이터 자동화 삽질기 (3/3) (1) | 2025.06.03 |
---|---|
꾸역 꾸역 일러스트레이터 자동화 삽질기 (2/3) (1) | 2025.06.03 |
꾸역 꾸역 일러스트레이터 자동화 삽질기 (1/3) (1) | 2025.06.03 |
MCP를 활용한 챗봇 구축기 - REST API 서버 편 (5/6) (0) | 2025.05.11 |
MCP를 활용한 챗봇 구축기 - 클라이언트 편 (4/6) (0) | 2025.05.11 |
MCP를 활용한 챗봇 구축기 - MCP 툴 기반으로 확장해보기 개요 (3/6) (0) | 2025.05.07 |
MCP를 활용한 챗봇 구축기 - RestAPI를 적용 (2/6) (0) | 2025.05.07 |
MCP를 활용한 챗봇 구축기 - 장대한 서막 (1/6) (2) | 2025.04.30 |