본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 27. · 2 Views
Agent-Optimized Tool Set 설계 실습 가이드
AI 에이전트가 효율적으로 사용할 수 있는 통합 도구 세트를 설계하는 방법을 배웁니다. FileSystem, Web, Database 도구를 MCP 프로토콜로 패키징하여 토큰 효율성과 명확성을 극대화하는 실전 기술을 다룹니다.
목차
- 툴_요구사항_분석_및_통합_기회_식별
- FileSystem_Tool_설계
- Web_Tool_설계
- Database_Tool_설계
- 통합_원칙_적용_모호성_제거
- Token_Efficiency_응답_형식_옵션_구현
- MCP_프로토콜로_툴_패키징_및_테스트
1. 툴 요구사항 분석 및 통합 기회 식별
어느 날 김개발 씨는 AI 에이전트 프로젝트를 담당하게 되었습니다. 처음에는 간단해 보였습니다.
파일 읽기, 웹 검색, 데이터베이스 조회 기능만 추가하면 될 것 같았습니다. 하지만 도구가 20개, 30개로 늘어나자 에이전트가 혼란스러워하기 시작했습니다.
툴 요구사항 분석은 에이전트가 어떤 작업을 수행해야 하는지 파악하고, 비슷한 기능을 하나로 묶을 수 있는 통합 기회를 찾는 과정입니다. 마치 주방을 정리할 때 비슷한 조리도구를 한 서랍에 모아두는 것과 같습니다.
이를 통해 에이전트의 의사결정 부담을 줄이고 정확도를 높일 수 있습니다.
다음 코드를 살펴봅시다.
// 도구 요구사항 분석 프레임워크
interface ToolRequirement {
action: string; // 수행할 작업
domain: string; // 작업 영역 (filesystem, web, database)
frequency: 'high' | 'medium' | 'low'; // 사용 빈도
dependencies: string[]; // 의존하는 다른 도구
}
// 통합 전: 분산된 도구들
const fragmentedTools = [
'readFile', 'writeFile', 'deleteFile', 'searchFile',
'fetchUrl', 'searchWeb', 'extractContent',
'queryDb', 'insertDb', 'updateDb', 'getSchema'
];
// 통합 후: 도메인별 그룹화
const integratedTools = {
filesystem: ['read', 'write', 'search'], // 3개로 통합
web: ['fetch', 'search', 'extract'], // 3개로 통합
database: ['query', 'update', 'schema'] // 3개로 통합
};
김개발 씨는 입사 6개월 차 주니어 개발자입니다. 최근 회사에서 AI 에이전트 프로젝트를 시작했는데, 그에게 도구 설계를 맡겼습니다.
처음에는 자신감이 넘쳤습니다. 필요한 기능마다 도구를 하나씩 만들면 되니까요.
readFile, writeFile, appendFile, deleteFile, copyFile, moveFile... 파일 관련 도구만 6개가 되었습니다.
여기에 웹 관련, 데이터베이스 관련 도구를 더하니 금세 30개가 넘었습니다. 문제는 에이전트의 성능이었습니다.
도구가 많아지니 에이전트가 어떤 도구를 선택해야 할지 헷갈려하기 시작했습니다. 파일을 읽어야 할 때 readFile을 써야 할지, getFileContent를 써야 할지 망설였습니다.
선배 개발자 박시니어 씨가 다가와 조언했습니다. "도구가 너무 많으면 에이전트도 사람처럼 혼란스러워해요.
인지 부하라고 하죠." 그렇다면 툴 요구사항 분석이란 무엇일까요? 쉽게 비유하자면, 이것은 마치 이사할 때 짐을 정리하는 것과 같습니다.
주방용품은 주방 상자에, 욕실용품은 욕실 상자에 담습니다. 아무렇게나 섞어 담으면 나중에 필요한 물건을 찾기 어렵습니다.
도구 설계도 마찬가지입니다. 분석의 첫 단계는 도메인 식별입니다.
에이전트가 다루는 영역을 크게 나눕니다. 대부분의 에이전트는 파일시스템, 웹, 데이터베이스라는 세 가지 핵심 영역에서 작업합니다.
두 번째 단계는 액션 매핑입니다. 각 도메인에서 에이전트가 수행하는 핵심 작업을 나열합니다.
파일시스템에서는 읽기, 쓰기, 검색이 핵심입니다. 삭제나 이동은 읽기와 쓰기의 조합으로 처리할 수 있습니다.
세 번째 단계는 통합 기회 식별입니다. 비슷한 기능을 하나로 묶을 수 있는지 살펴봅니다.
readFile과 getFileContent는 사실 같은 작업입니다. 하나로 합치면 됩니다.
박시니어 씨가 덧붙였습니다. "좋은 도구 세트는 MECE 원칙을 따라야 해요.
상호 배타적이고 전체를 포괄하는 거죠." 김개발 씨는 이 원칙에 따라 30개의 도구를 9개로 줄였습니다. 파일시스템 3개, 웹 3개, 데이터베이스 3개.
에이전트의 정확도가 눈에 띄게 향상되었습니다. 주의할 점도 있습니다.
너무 과도하게 통합하면 안 됩니다. 하나의 도구가 너무 많은 일을 하면 오히려 복잡해집니다.
적절한 추상화 수준을 찾는 것이 핵심입니다.
실전 팁
💡 - 도구가 10개를 넘어가면 통합 기회를 적극적으로 찾아보세요
- 도메인별로 3-5개의 핵심 도구만 유지하는 것이 이상적입니다
2. FileSystem Tool 설계
김개발 씨는 파일 관련 도구부터 정리하기로 했습니다. 기존에는 readFile, writeFile, searchFile, listDirectory, getFileInfo 등 8개의 도구가 있었습니다.
이것들을 어떻게 하나의 통합된 FileSystem 도구로 만들 수 있을까요?
FileSystem Tool은 파일 읽기, 쓰기, 검색 기능을 하나의 인터페이스로 통합한 도구입니다. 마치 스위스 아미 나이프처럼 하나의 도구에 여러 기능이 담겨 있지만, 각 기능은 명확하게 구분됩니다.
중요한 것은 작업 유형을 명시적으로 지정하여 모호성을 제거하는 것입니다.
다음 코드를 살펴봅시다.
// 통합 FileSystem Tool 설계
interface FileSystemTool {
name: 'filesystem';
description: '파일 시스템 작업을 수행합니다';
parameters: {
operation: 'read' | 'write' | 'search'; // 필수: 작업 유형
path: string; // 대상 경로
content?: string; // write 시 필요
pattern?: string; // search 시 필요
options?: {
encoding?: 'utf-8' | 'base64';
recursive?: boolean;
maxResults?: number;
};
};
}
// 사용 예시
const readExample = {
operation: 'read',
path: '/src/index.ts',
options: { encoding: 'utf-8' }
};
const searchExample = {
operation: 'search',
path: '/src',
pattern: '*.tsx',
options: { recursive: true, maxResults: 100 }
};
박시니어 씨가 화이트보드 앞에 섰습니다. "파일시스템 도구를 설계할 때 가장 중요한 건 뭘까요?" 김개발 씨가 대답했습니다.
"음, 모든 기능을 다 넣는 거요?" 박시니어 씨가 고개를 저었습니다. "아니요, 에이전트가 헷갈리지 않게 만드는 거예요." 기존의 분산된 도구들을 살펴봅시다.
readFile은 파일을 읽고, writeFile은 파일을 씁니다. 명확해 보입니다.
하지만 문제는 에이전트가 "파일에서 특정 내용을 찾아서 수정해줘"라는 요청을 받았을 때 발생합니다. 이때 에이전트는 searchFile을 먼저 호출해야 할까요, 아니면 readFile로 내용을 읽고 직접 검색해야 할까요?
도구가 분리되어 있으면 이런 결정을 매번 해야 합니다. 통합 FileSystem Tool은 이 문제를 해결합니다.
operation 파라미터 하나로 모든 것이 결정됩니다. read면 읽기, write면 쓰기, search면 검색.
간단합니다. 설계의 핵심 원칙을 살펴보겠습니다.
첫째, 필수 파라미터를 명확히 합니다. operation과 path는 모든 작업에 필수입니다.
에이전트가 이 두 가지만 정하면 기본적인 작업이 가능합니다. 둘째, 조건부 파라미터를 분리합니다.
content는 write 작업에만 필요합니다. pattern은 search 작업에만 필요합니다.
이렇게 하면 에이전트가 불필요한 파라미터를 신경 쓰지 않아도 됩니다. 셋째, 옵션은 합리적인 기본값을 가집니다.
encoding은 기본적으로 utf-8입니다. recursive는 기본적으로 false입니다.
대부분의 경우 옵션을 지정하지 않아도 원하는 결과를 얻을 수 있어야 합니다. 코드를 자세히 살펴보겠습니다.
operation 필드는 유니온 타입으로 정의되어 있습니다. 'read', 'write', 'search' 세 가지 값만 가능합니다.
이렇게 하면 에이전트가 잘못된 값을 입력할 가능성이 사라집니다. options 객체는 선택적입니다.
물음표가 붙어 있어서 생략해도 됩니다. 하지만 세밀한 제어가 필요할 때는 언제든 사용할 수 있습니다.
실무에서 이 패턴이 빛을 발하는 순간이 있습니다. 에이전트가 "src 폴더에서 모든 TypeScript 파일을 찾아서 각각의 내용을 읽어줘"라는 요청을 받았다고 가정해봅시다.
통합 도구를 사용하면 에이전트의 사고가 단순해집니다. 먼저 filesystem 도구로 search 작업을 수행하고, 결과를 받아서 각 파일에 대해 read 작업을 수행합니다.
도구 선택에 고민할 필요가 없습니다. 박시니어 씨가 정리했습니다.
"도구 설계의 목표는 에이전트가 작업에만 집중하게 만드는 거예요. 어떤 도구를 써야 할지 고민하는 시간을 줄여주는 거죠."
실전 팁
💡 - operation 파라미터는 반드시 열거형(enum)이나 유니온 타입으로 제한하세요
- 선택적 파라미터에는 항상 합리적인 기본값을 설정하세요
3. Web Tool 설계
파일시스템 도구를 완성한 김개발 씨는 이제 웹 관련 도구에 도전합니다. fetchUrl, parseHtml, searchGoogle, extractText...
웹 작업은 파일시스템보다 더 다양한 기능이 필요해 보였습니다. 이것들을 어떻게 깔끔하게 통합할 수 있을까요?
Web Tool은 URL 페치, 웹 검색, 콘텐츠 추출 기능을 통합합니다. 웹 작업의 특성상 네트워크 지연과 에러 처리가 중요합니다.
마치 도서관 사서가 책을 찾고, 필요한 부분을 복사해주는 것처럼, Web Tool은 정보를 가져오고 원하는 형태로 가공해서 전달합니다.
다음 코드를 살펴봅시다.
// 통합 Web Tool 설계
interface WebTool {
name: 'web';
description: '웹 리소스를 가져오고 검색합니다';
parameters: {
operation: 'fetch' | 'search' | 'extract';
target: string; // URL 또는 검색어
options?: {
// fetch 옵션
method?: 'GET' | 'POST';
headers?: Record<string, string>;
timeout?: number;
// search 옵션
maxResults?: number;
dateRange?: 'day' | 'week' | 'month' | 'year';
// extract 옵션
selector?: string; // CSS 선택자
format?: 'text' | 'html' | 'markdown';
};
};
returns: {
success: boolean;
data?: string | SearchResult[];
error?: string;
metadata?: { statusCode: number; contentType: string };
};
}
// 체이닝 예시: 검색 후 추출
const workflow = [
{ operation: 'search', target: 'TypeScript MCP tutorial' },
{ operation: 'fetch', target: '{{searchResults[0].url}}' },
{ operation: 'extract', target: '{{fetchedContent}}',
options: { selector: 'article', format: 'markdown' }}
];
김개발 씨가 웹 도구 설계에 착수했을 때, 가장 먼저 든 생각은 "웹 작업은 종류가 너무 많다"였습니다. URL을 가져오는 것, 검색하는 것, HTML을 파싱하는 것, 텍스트를 추출하는 것...
각각 다른 도구가 필요해 보였습니다. 하지만 박시니어 씨는 다른 관점을 제시했습니다.
"웹 작업의 본질을 생각해봐요. 결국 정보를 가져오는 것 아닌가요?" 이 관점에서 보면 모든 웹 작업은 세 가지로 압축됩니다.
첫째, 특정 URL의 콘텐츠를 가져오기(fetch). 둘째, 인터넷에서 정보를 검색하기(search).
셋째, 가져온 콘텐츠에서 원하는 부분을 추출하기(extract). 이 세 가지 작업은 종종 연속으로 일어납니다.
"TypeScript 튜토리얼을 검색해서 첫 번째 결과의 본문을 마크다운으로 가져와줘"라는 요청을 생각해봅시다. 검색하고, 페치하고, 추출합니다.
자연스러운 흐름입니다. Web Tool의 설계에서 주목할 점은 target 파라미터입니다.
이 파라미터는 작업에 따라 의미가 달라집니다. fetch 작업에서는 URL이고, search 작업에서는 검색어이고, extract 작업에서는 추출 대상 콘텐츠입니다.
이런 설계는 위험해 보일 수 있습니다. 같은 파라미터가 다른 의미를 가지면 혼란스럽지 않을까요?
하지만 실제로는 그렇지 않습니다. operation과 함께 보면 의미가 명확해집니다.
options 객체를 살펴보겠습니다. 각 작업에 필요한 옵션이 한 곳에 모여 있습니다.
fetch에는 method와 headers가 필요하고, search에는 maxResults와 dateRange가 필요하고, extract에는 selector와 format이 필요합니다. 이렇게 한 곳에 모아두면 에이전트가 필요한 옵션을 쉽게 찾을 수 있습니다.
물론 해당 작업에 맞지 않는 옵션은 무시됩니다. fetch 작업에서 selector를 지정해도 아무 일도 일어나지 않습니다.
returns 구조도 중요합니다. 모든 작업이 동일한 형태의 응답을 반환합니다.
success 필드로 성공 여부를 확인하고, data 필드에서 결과를 받고, 문제가 생기면 error 필드를 확인합니다. 일관된 응답 구조는 에이전트의 에러 처리를 단순하게 만듭니다.
실무에서 Web Tool이 특히 유용한 경우가 있습니다. 에이전트가 최신 정보를 필요로 할 때입니다.
검색으로 관련 페이지를 찾고, 페치로 내용을 가져오고, 추출로 핵심만 뽑아냅니다. 세 번의 도구 호출로 완벽한 결과를 얻습니다.
주의할 점은 타임아웃 설정입니다. 웹 요청은 언제든 실패할 수 있습니다.
합리적인 타임아웃 기본값(예: 30초)을 설정하고, 필요하면 조절할 수 있게 해야 합니다.
실전 팁
💡 - 웹 요청에는 항상 타임아웃을 설정하세요. 기본값 30초가 적당합니다
- extract 작업에서 CSS 선택자는 너무 구체적이면 깨지기 쉽습니다. 유연한 선택자를 사용하세요
4. Database Tool 설계
김개발 씨의 프로젝트에는 데이터베이스 작업도 필수였습니다. 사용자 정보 조회, 기록 저장, 통계 분석...
그런데 데이터베이스 도구는 특히 주의가 필요했습니다. 잘못된 쿼리 하나가 전체 데이터를 날릴 수도 있으니까요.
Database Tool은 쿼리 실행, 데이터 수정, 스키마 조회 기능을 제공합니다. 데이터베이스 작업은 안전성이 핵심입니다.
마치 금고를 다루듯이, 읽기 작업과 쓰기 작업을 명확히 구분하고, 위험한 작업에는 추가적인 확인 절차를 둡니다.
다음 코드를 살펴봅시다.
// 통합 Database Tool 설계
interface DatabaseTool {
name: 'database';
description: '데이터베이스 작업을 수행합니다';
parameters: {
operation: 'query' | 'update' | 'schema';
// query/update: SQL 또는 구조화된 쿼리
query?: string | StructuredQuery;
// schema: 테이블명 또는 전체
table?: string;
options?: {
database?: string; // 대상 데이터베이스
limit?: number; // 결과 제한 (기본: 100)
dryRun?: boolean; // update 미리보기 (기본: false)
confirmDangerous?: boolean; // DELETE/DROP 확인
};
};
}
interface StructuredQuery {
type: 'select' | 'insert' | 'update' | 'delete';
table: string;
columns?: string[];
where?: Record<string, any>;
values?: Record<string, any>;
orderBy?: { column: string; direction: 'asc' | 'desc' };
}
// 안전한 사용 예시
const safeQuery = {
operation: 'query',
query: { type: 'select', table: 'users',
columns: ['id', 'name'],
where: { active: true } },
options: { limit: 50 }
};
박시니어 씨가 진지한 표정으로 말했습니다. "데이터베이스 도구는 특별히 신중하게 설계해야 해요.
한 번의 실수로 몇 년치 데이터가 사라질 수 있거든요." 김개발 씨도 그 심각성을 알고 있었습니다. 예전에 실수로 WHERE 절 없이 DELETE를 실행한 동료의 이야기를 들은 적이 있습니다.
그 후로 회사 전체가 백업 정책을 강화했다고 합니다. 그래서 Database Tool의 설계에서 가장 중요한 것은 안전장치입니다.
첫 번째 안전장치는 작업 유형의 명확한 구분입니다. query는 읽기 전용입니다.
데이터를 조회만 하고 변경하지 않습니다. update는 쓰기 작업입니다.
INSERT, UPDATE, DELETE가 여기에 해당합니다. schema는 데이터베이스 구조를 조회합니다.
두 번째 안전장치는 구조화된 쿼리입니다. 원시 SQL 문자열 대신 StructuredQuery 인터페이스를 사용하면 SQL 인젝션 위험을 원천 차단할 수 있습니다.
에이전트가 직접 SQL을 작성하는 것보다 훨씬 안전합니다. 세 번째 안전장치는 dryRun 옵션입니다.
update 작업 전에 dryRun을 true로 설정하면 실제로 변경하지 않고 "몇 개의 행이 영향받을지" 미리 확인할 수 있습니다. 마치 드라이 클리닝처럼, 실제 작업 전에 결과를 예측합니다.
네 번째 안전장치는 confirmDangerous 플래그입니다. DELETE나 DROP 같은 위험한 작업은 이 플래그가 true가 아니면 실행을 거부합니다.
에이전트가 실수로 데이터를 삭제하는 것을 막아줍니다. 코드에서 StructuredQuery 인터페이스를 자세히 살펴봅시다.
type 필드로 어떤 종류의 쿼리인지 명시합니다. select, insert, update, delete 네 가지입니다.
table 필드로 대상 테이블을 지정합니다. where 필드가 특히 중요합니다.
Record<string, any> 타입으로, 키-값 쌍으로 조건을 지정합니다. { active: true }는 "WHERE active = true"로 변환됩니다.
이 방식은 SQL 인젝션이 불가능합니다. 실무에서 이 설계가 빛을 발하는 상황이 있습니다.
에이전트에게 "비활성 사용자를 모두 삭제해줘"라고 요청했다고 가정합시다. 잘 설계된 Database Tool은 이렇게 동작합니다.
먼저 dryRun으로 "500명의 사용자가 삭제될 예정입니다"라고 알려줍니다. 그리고 confirmDangerous 확인을 요청합니다.
사용자가 확인하면 그제야 실제 삭제를 수행합니다. limit 옵션의 기본값도 주목할 만합니다.
100으로 설정되어 있습니다. 에이전트가 실수로 백만 개의 행을 조회해서 메모리를 폭발시키는 것을 방지합니다.
필요하면 늘릴 수 있지만, 기본값이 안전한 쪽으로 설정되어 있습니다.
실전 팁
💡 - update 작업 전에는 항상 dryRun으로 영향 범위를 확인하세요
- 가능하면 원시 SQL 대신 StructuredQuery를 사용하여 안전성을 확보하세요
5. 통합 원칙 적용 모호성 제거
김개발 씨가 세 가지 도구를 완성했을 때, 박시니어 씨가 질문했습니다. "만약 에이전트가 filesystem의 read 대신 web의 fetch를 사용하면 어떻게 될까요?" 김개발 씨는 당황했습니다.
file:// 프로토콜을 쓰면 둘 다 파일을 읽을 수 있으니까요.
모호성 제거는 에이전트가 잘못된 도구를 선택할 가능성을 원천 차단하는 것입니다. 마치 교통 표지판처럼, 어떤 상황에서 어떤 도구를 써야 하는지 명확하게 안내해야 합니다.
도구의 이름, 설명, 파라미터 모두가 이 목표를 위해 설계되어야 합니다.
다음 코드를 살펴봅시다.
// 모호성 제거 원칙 적용 예시
// 나쁜 설계: 모호한 설명
const ambiguousTool = {
name: 'getData',
description: '데이터를 가져옵니다', // 어떤 데이터? 어디서?
parameters: { source: 'string' } // URL? 파일? DB?
};
// 좋은 설계: 명확한 설명
const clearTools = {
filesystem: {
name: 'filesystem',
description: '로컬 파일 시스템의 파일을 읽고, 쓰고, 검색합니다. ' +
'웹 리소스는 web 도구를, 데이터베이스는 database 도구를 사용하세요.',
when_to_use: '로컬 파일 작업 시',
when_not_to_use: 'URL 접근, DB 쿼리 시'
},
web: {
name: 'web',
description: 'HTTP/HTTPS URL에서 콘텐츠를 가져오고 웹 검색을 수행합니다. ' +
'로컬 파일은 filesystem 도구를 사용하세요.',
when_to_use: '웹 페이지, API 호출 시',
when_not_to_use: '로컬 파일 읽기, file:// 프로토콜'
},
database: {
name: 'database',
description: '데이터베이스에서 데이터를 조회하고 수정합니다. ' +
'파일로 저장된 데이터는 filesystem 도구를 사용하세요.',
when_to_use: 'SQL 데이터베이스 작업 시',
when_not_to_use: 'JSON 파일, CSV 파일 처리'
}
};
모호성은 에이전트 도구 설계에서 가장 큰 적입니다. 김개발 씨는 이 교훈을 어렵게 배웠습니다.
처음에 그가 만든 도구 설명은 이랬습니다. "filesystem: 파일을 다룹니다", "web: 웹 데이터를 가져옵니다", "database: 데이터베이스를 사용합니다".
간결하고 좋아 보였습니다. 하지만 테스트에서 문제가 드러났습니다.
에이전트에게 "config.json 파일을 읽어줘"라고 요청했습니다. 에이전트는 web 도구의 fetch 작업을 선택했습니다.
왜? JSON은 웹에서 많이 쓰이는 형식이니까요.
물론 틀린 선택이었습니다. 또 다른 예로, "사용자 데이터를 가져와줘"라고 요청했습니다.
에이전트는 어떤 도구를 써야 할지 한참을 고민했습니다. users.json 파일인가요?
API 엔드포인트인가요? users 테이블인가요?
정보가 부족했습니다. 박시니어 씨가 해결책을 제시했습니다.
경계를 명확히 하라는 것이었습니다. 좋은 도구 설명에는 세 가지 요소가 필요합니다.
첫째, 무엇을 하는지 명확히. 둘째, 언제 사용하는지 구체적으로.
셋째, 언제 사용하지 말아야 하는지 분명하게. 세 번째가 특히 중요합니다.
"사용하지 말아야 할 때"를 명시하면 도구 간의 경계가 선명해집니다. 코드의 clearTools 예시를 보세요.
filesystem 도구의 설명에는 "웹 리소스는 web 도구를, 데이터베이스는 database 도구를 사용하세요"라고 명시되어 있습니다. 다른 도구로 안내하는 것입니다.
이것은 마치 도로 표지판과 같습니다. "서울 → 이쪽" 표지판만 있으면 헷갈릴 수 있습니다.
"서울 → 이쪽, 부산 → 저쪽"이라고 하면 훨씬 명확해집니다. when_to_use와 when_not_to_use 필드를 추가한 것도 주목하세요.
이 필드들은 실제 도구 스키마에 포함되어 에이전트에게 전달됩니다. 에이전트가 도구를 선택할 때 이 정보를 참고합니다.
실제 개선 효과는 놀라웠습니다. 모호한 설명을 사용했을 때 도구 선택 정확도는 약 70%였습니다.
명확한 설명으로 바꾸니 95% 이상으로 올라갔습니다. 하나 더 주의할 점이 있습니다.
파라미터 이름도 명확해야 합니다. source보다는 filePath나 url이 좋습니다.
data보다는 content나 payload가 좋습니다. 이름만 봐도 무엇을 넣어야 하는지 알 수 있어야 합니다.
실전 팁
💡 - 도구 설명에 "다른 도구를 써야 할 경우"를 반드시 명시하세요
- 파라미터 이름은 그 자체로 설명이 되도록 구체적으로 지으세요
6. Token Efficiency 응답 형식 옵션 구현
도구가 잘 작동하기 시작했지만, 새로운 문제가 나타났습니다. 에이전트가 파일 목록을 요청할 때마다 수천 개의 파일 정보가 반환되었습니다.
토큰 비용이 치솟고, 응답 시간도 느려졌습니다. 김개발 씨는 "필요한 정보만 간결하게 받을 순 없을까?"라고 고민했습니다.
Token Efficiency는 에이전트와 도구 사이에 오가는 데이터의 양을 최적화하는 것입니다. 마치 택배 포장처럼, 내용물에 맞는 크기의 상자를 선택해야 합니다.
너무 크면 낭비고, 너무 작으면 못 담습니다. 응답 형식 옵션을 통해 에이전트가 필요한 만큼만 받을 수 있게 합니다.
다음 코드를 살펴봅시다.
// 응답 형식 옵션 구현
interface ResponseFormatOptions {
format: 'minimal' | 'standard' | 'detailed';
fields?: string[]; // 특정 필드만 포함
maxLength?: number; // 텍스트 최대 길이
truncate?: boolean; // 초과 시 자르기
}
// FileSystem Tool with Token Efficiency
interface FileSystemResponse {
// minimal: 핵심만
minimal: { path: string; exists: boolean };
// standard: 일반적인 사용
standard: {
path: string;
content: string;
size: number;
modified: string;
};
// detailed: 모든 정보
detailed: {
path: string;
content: string;
size: number;
created: string;
modified: string;
permissions: string;
encoding: string;
lineCount: number;
metadata: Record<string, any>;
};
}
// 사용 예시
const efficientRequest = {
operation: 'read',
path: '/src/index.ts',
responseFormat: {
format: 'minimal', // 존재 여부만 확인
fields: ['path', 'exists']
}
};
const detailedRequest = {
operation: 'read',
path: '/src/index.ts',
responseFormat: {
format: 'standard',
maxLength: 5000, // 내용 5000자로 제한
truncate: true
}
};
AI 에이전트 개발에서 토큰은 곧 비용입니다. 그리고 비용만의 문제가 아닙니다.
김개발 씨는 테스트 중에 이상한 현상을 발견했습니다. 간단한 작업인데 에이전트가 느리게 반응했습니다.
원인을 추적해보니 도구 응답이 너무 컸습니다. 파일 내용 전체, 메타데이터 전체, 히스토리 전체...
불필요한 정보가 쏟아지고 있었습니다. 더 심각한 문제도 있었습니다.
응답이 너무 길면 에이전트가 중요한 정보를 놓칠 수 있습니다. 마치 두꺼운 보고서에서 핵심을 찾기 어려운 것처럼, 에이전트도 과도한 정보에 압도당합니다.
해결책은 응답 형식 옵션입니다. 세 가지 기본 형식을 정의했습니다.
minimal은 가장 간결합니다. 파일이 존재하는지, 작업이 성공했는지 정도만 알려줍니다.
예/아니오로 답할 수 있는 질문에 적합합니다. standard는 일반적인 사용에 적합합니다.
파일 내용, 크기, 수정 시간 등 대부분의 작업에 필요한 정보를 포함합니다. 기본값으로 적당합니다.
detailed는 모든 정보를 포함합니다. 권한, 인코딩, 줄 수, 추가 메타데이터까지.
디버깅이나 상세 분석이 필요할 때 사용합니다. 코드에서 fields 옵션을 주목하세요.
원하는 필드만 명시적으로 지정할 수 있습니다. ['path', 'size']만 필요하다면 나머지는 전송하지 않습니다.
이것만으로도 토큰 사용량이 크게 줄어듭니다. maxLength와 truncate 옵션도 중요합니다.
파일 내용이 10만 자라도 처음 5000자만 필요할 수 있습니다. maxLength로 제한하고 truncate를 true로 설정하면 초과분을 잘라냅니다.
실제로 이 최적화가 얼마나 효과적일까요? 김개발 씨의 테스트 결과를 보면 놀랍습니다.
동일한 파일 읽기 작업에서 detailed 형식은 약 2000토큰을 사용했습니다. standard는 800토큰, minimal은 50토큰이었습니다.
40배 차이입니다. 에이전트가 단순히 "이 파일이 있어?"라고 확인할 때 detailed 형식을 쓸 이유가 없습니다.
minimal로 충분합니다. 이런 작은 최적화가 쌓이면 전체 비용이 크게 줄어듭니다.
박시니어 씨가 조언했습니다. "기본값은 standard로 하되, 에이전트가 상황에 맞게 형식을 선택할 수 있게 해주세요.
스마트한 에이전트라면 알아서 효율적인 선택을 할 거예요."
실전 팁
💡 - 기본 응답 형식은 standard로 설정하고, minimal은 확인 작업에 활용하세요
- 대용량 텍스트는 항상 maxLength 옵션으로 제한하는 것이 안전합니다
7. MCP 프로토콜로 툴 패키징 및 테스트
드디어 마지막 단계입니다. 김개발 씨가 설계한 세 가지 도구를 실제로 사용할 수 있게 만들어야 합니다.
MCP(Model Context Protocol)는 AI 에이전트와 도구를 연결하는 표준 프로토콜입니다. 이것을 사용하면 어떤 에이전트든 동일한 방식으로 도구를 사용할 수 있습니다.
MCP 프로토콜은 AI 모델과 외부 도구 사이의 표준 통신 규약입니다. 마치 USB가 다양한 기기를 컴퓨터에 연결하듯이, MCP는 다양한 도구를 AI 에이전트에 연결합니다.
도구를 MCP 서버로 패키징하면 Claude, GPT 등 어떤 에이전트에서든 사용할 수 있습니다.
다음 코드를 살펴봅시다.
// MCP 서버로 도구 패키징
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { z } from 'zod';
// MCP 서버 생성
const server = new McpServer({
name: 'agent-tools',
version: '1.0.0'
});
// FileSystem Tool 등록
server.tool(
'filesystem',
'로컬 파일 시스템 작업을 수행합니다',
{
operation: z.enum(['read', 'write', 'search']),
path: z.string().describe('대상 파일 또는 디렉토리 경로'),
content: z.string().optional(),
pattern: z.string().optional(),
responseFormat: z.enum(['minimal', 'standard', 'detailed']).default('standard')
},
async ({ operation, path, content, pattern, responseFormat }) => {
// 작업 수행 로직
const result = await executeFilesystemOp(operation, path, content, pattern);
return formatResponse(result, responseFormat);
}
);
// 서버 시작
const transport = new StdioServerTransport();
await server.connect(transport);
모든 설계가 완료되었습니다. 이제 실제로 작동하는 코드로 만들 차례입니다.
MCP는 Model Context Protocol의 약자입니다. Anthropic이 주도하여 개발한 오픈 프로토콜로, AI 에이전트와 외부 도구 사이의 통신을 표준화합니다.
마치 웹의 HTTP처럼, 모두가 같은 규약을 따르면 상호운용성이 확보됩니다. MCP 서버를 만드는 과정을 단계별로 살펴보겠습니다.
첫 번째 단계는 의존성 설치입니다. @modelcontextprotocol/sdk 패키지가 필요합니다.
이 패키지에는 서버를 만들고 통신을 처리하는 모든 도구가 포함되어 있습니다. 두 번째 단계는 서버 인스턴스 생성입니다.
McpServer 클래스를 사용합니다. name과 version은 필수입니다.
이 정보는 에이전트가 서버를 식별하는 데 사용됩니다. 세 번째 단계는 도구 등록입니다.
server.tool() 메서드를 사용합니다. 첫 번째 인자는 도구 이름, 두 번째는 설명, 세 번째는 파라미터 스키마, 네 번째는 실제 실행 함수입니다.
파라미터 스키마에 Zod를 사용하는 것에 주목하세요. Zod는 런타임 타입 검증 라이브러리입니다.
에이전트가 잘못된 파라미터를 보내면 자동으로 에러가 발생합니다. 타입 안전성이 보장됩니다.
z.enum(['read', 'write', 'search'])는 operation이 이 세 값 중 하나여야 한다고 선언합니다. z.string().optional()은 선택적 문자열 파라미터입니다.
.describe()로 파라미터 설명을 추가할 수 있습니다. 네 번째 단계는 전송 계층 연결입니다.
StdioServerTransport는 표준 입출력을 통해 통신합니다. 가장 간단하고 널리 사용되는 방식입니다.
HTTP나 WebSocket 전송도 가능합니다. 마지막으로 server.connect()를 호출하면 서버가 시작됩니다.
이제 에이전트의 요청을 기다립니다. 테스트는 어떻게 할까요?
MCP Inspector라는 도구가 있습니다. 브라우저에서 서버에 연결하여 각 도구를 직접 호출해볼 수 있습니다.
개발 중 디버깅에 매우 유용합니다. 실제 에이전트와 연결하려면 설정 파일이 필요합니다.
Claude Desktop의 경우 claude_desktop_config.json에 서버 경로를 등록합니다. 그러면 Claude가 자동으로 서버를 시작하고 도구를 사용할 수 있게 됩니다.
김개발 씨가 서버를 완성하고 테스트했을 때, 모든 것이 완벽하게 작동했습니다. 에이전트가 filesystem 도구로 파일을 읽고, web 도구로 검색하고, database 도구로 쿼리를 실행했습니다.
세 개의 통합 도구로 이전의 30개 도구가 하던 모든 일을 처리했습니다. 박시니어 씨가 미소 지었습니다.
"축하해요. 이제 진짜 에이전트 개발자가 됐네요."
실전 팁
💡 - 개발 중에는 MCP Inspector로 도구를 테스트하세요. 실제 에이전트 없이도 검증할 수 있습니다
- Zod 스키마에 describe()를 적극 활용하세요. 에이전트가 파라미터의 용도를 더 잘 이해합니다
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Context Degradation 패턴 마스터
AI 모델에게 전달하는 컨텍스트가 많아질수록 오히려 성능이 떨어지는 현상을 다룹니다. 프로덕션 환경에서 발생하는 5가지 주요 패턴과 이를 완화하는 4가지 전략을 실전 사례와 함께 살펴봅니다.
Context Fundamentals 완벽 가이드 AI 에이전트 맥락 이해하기
AI 에이전트 시스템에서 Context(맥락)가 무엇인지, 어떻게 구성되고, 왜 효율적인 관리가 중요한지 알아봅니다. Attention Budget, Progressive Disclosure 원칙을 통해 실무에서 활용할 수 있는 맥락 엔지니어링 기법을 배웁니다.
Production-Grade AI Agent System 완벽 가이드
연구 어시스턴트 기능을 갖춘 프로덕션급 AI 에이전트 시스템을 처음부터 끝까지 구축하는 방법을 다룹니다. 멀티 에이전트 아키텍처, 메모리 시스템, 평가 체계까지 실무에서 바로 적용할 수 있는 내용을 담았습니다.
LLM-as-a-Judge 평가 시스템 완벽 가이드
LLM을 활용하여 AI 에이전트의 출력을 체계적으로 평가하는 방법을 다룹니다. Direct Scoring, Pairwise Comparison, 편향 완화 기법부터 실제 대시보드 구현까지 실습 중심으로 설명합니다.
Knowledge Graph 메모리 시스템 완벽 가이드
AI 에이전트에 장기 기억 능력을 부여하는 Knowledge Graph 메모리 시스템을 구축합니다. Working, Short-term, Long-term 메모리 아키텍처부터 Neo4j를 활용한 Temporal Knowledge Graph 구현까지 실습합니다.