본 문서는 최신 AI 애플리케이션 개발의 3대 핵심 요소인 Skills(도구), Agent(에이전트), 그리고 MCP(표준 프로토콜)의 개념을 정리하고 실습하기 위해 작성되었습니다.
AI가 단순히 채팅을 하는 수준을 넘어, 실제 업무를 수행하기 위해서는 다음 세 가지 요소의 조화가 필요합니다.
| 구분 | Skills (기술/도구) | Agent (에이전트) | MCP (프로토콜) |
|---|---|---|---|
| 역할 | 특정 작업을 수행하는 함수 | 목표 달성을 위해 판단하는 주체 | 모델과 도구를 연결하는 표준 규격 |
| 성격 | 수동적 (호출 대기) | 능동적 (자율적 계획 및 실행) | 인프라적 (연결의 표준화) |
| 비유 | 요리사의 '칼'과 '불' | 코스 요리를 완성하는 '셰프' | 모든 기구를 꽂는 '공통 콘센트' |
| 핵심 키워드 | API, Function Calling | Planning, Reasoning, Tool Use | Interoperability, Host-Server |
핵심 원리: LLM은 코드를 직접 실행하는 것이 아니라, "지금 이 상황에서는 A라는 함수를 B라는 파라미터로 실행해줘"라고 결정(Function Calling)만 합니다. 실제 실행은 우리 시스템(백엔드)이 수행합니다.
함수 본체 (Implementation): 실제 로직이 수행되는 코드 (Java, Python 등).
이름 (Name): AI가 함수를 식별하기 위한 고유 명칭 (예: get_user_info).
설명 (Description): 가장 중요함. AI가 "이 함수를 언제 써야 하는지" 판단하는 근거입니다. 자연어로 아주 상세히 적어야 합니다.
claude skils 예시
Claude의 Tool Use (Skills) 핵심 매커니즘
Claude에게 Skills를 제공한다는 것은, Claude에게 "너는 이런 능력이 있는 API를 호출할 권한이 있어"라고 정의해 주는 과정입니다.
Claude가 Skills를 처리하는 4단계 (Lifecycle)
정의 (Definition): 개발자가 Claude에게 도구 이름, 설명, 입력 파라미터 구조(JSON Schema)를 전달합니다.
판단 (Reasoning): 사용자의 질문을 받고, Claude는 자신이 가진 도구 목록 중 적합한 것이 있는지 판단합니다.
요청 (Tool Use Request): Claude가 답변 대신 "내가 직접 답할 순 없으니, get_stock_price 도구를 {"ticker": "AAPL"} 파라미터로 실행해줘"라는 특수한 형태의 요청을 보냅니다.
실행 및 결과 전달 (Tool Output): 개발자의 코드(백엔드)가 실제로 도구를 실행하고, 그 결과값을 다시 Claude에게 보내줍니다. 그러면 Claude가 그 결과를 읽고 최종 답변을 작성합니다.
✅ 상세한 가이드라인 제공
단순히 "날씨 조회"라고 하기보다, Claude에게는 다음과 같이 구체적으로 지시하는 것이 좋습니다.
"이 도구는 섭씨(Celsius) 단위로 온도를 반환합니다. 사용자가 화씨를 물어보면 이 도구를 실행한 후 결과를 변환해서 답하세요."
✅ XML 태그 활용 (Claude의 특기)
Claude는 구조화된 데이터를 다룰 때 XML 형식을 선호합니다. Skill 결과값을 줄 때도 XML 태그로 감싸서 주면 훨씬 더 정확하게 해석합니다.
JSON
{
"name": "get_article_details",
"description": "사내 지식베이스에서 특정 문서의 상세 내용을 가져옵니다.",
"input_schema": {
"type": "object",
"properties": {
"article_id": {
"type": "string",
"description": "문서 고유 ID (예: KB-1234)"
},
"include_comments": {
"type": "boolean",
"description": "댓글 포함 여부"
}
},
"required": ["article_id"]
}
}
작동 방식 = Claude가 직접 실행하는 것이 아니라, 실행해달라고 "요청"만 하는 것.
교육 포인트 = "개발자는 Claude가 기술을 정확히 쓸 수 있도록 매개변수 설계(Schema)와 자연어 설명(Description)을 완벽하게 작성해야 한다."
Skills에서 Agent로: 자율적 판단의 시작
단순한 Tool Use(Skills)와 Agent의 결정적인 차이는 '연쇄적 사고(Reasoning Chain)'와 '자율성'에 있습니다.
일반 Tool Use: "A를 해줘" -> (A 도구 실행) -> 끝.
Agent: "내일까지 이 보고서를 완성해서 팀장님께 메일 보내줘"
(판단) 보고서 데이터를 어디서 가져오지? -> DB 조회 Skill 사용
(판단) 가져온 데이터를 요약해야겠네. -> LLM 요약 진행
(판단) 메일 주소를 알아야겠어. -> 사원 검색 Skill 사용
(판단) 이제 메일을 보내자. -> Email 전송 Skill 사용
Planning (계획): 목표를 잘게 쪼개는 능력. (예: ReAct 프레임워크)
Memory (기억): 이전 단계에서 무엇을 했는지 기억하는 능력. (Short-term / Long-term)
Tools (기술): 우리가 앞서 배운 Skills의 집합.
Profile (역할): "너는 전문 회계사야", "너는 시스템 관리자야" 같은 페르소나 설정.
Step 1: 에이전트에게 줄 도구함(Tools) 준비
앞서 만든 Skills를 리스트로 묶습니다.
Python
tools = [get_inventory_status, calculate_tax, send_email]
Step 2: 에이전트 사고 방식(Reasoning) 설정
가장 대중적인 모델은 ReAct(Reason + Act) 방식입니다. "생각하고(Thought), 행동하고(Action), 관찰한다(Observation)"는 루프를 돕니다.
Step 3: 코드 구현 예시 (Python/LangGraph 스타일)
최근에는 흐름을 제어하기 위해 LangGraph나 LangChain의 create_react_agent를 많이 씁니다.
Python
from langchain_anthropic import ChatAnthropic
from langgraph.prebuilt import create_react_agent
# 1. 모델 설정 (Claude 3.5 Sonnet 추천)
model = ChatAnthropic(model="claude-3-5-sonnet-20240620")
# 2. 에이전트 생성 (모델 + 도구 + 지침)
system_message = "너는 사내 자산 관리 전문가야. 재고를 확인하고 부족하면 구매 승인을 요청해."
agent_executor = create_react_agent(model, tools, state_modifier=system_message)
# 3. 실행
response = agent_executor.invoke({"messages": [("user", "노트북 재고 확인하고 부족하면 구매팀에 메일 보내줘")]})
Orchestrator 패턴: 자바 코드가 전체 흐름을 제어하고, LLM에게는 "다음 단계에 무엇을 할지"만 묻는 방식입니다.
Function Call Loop: * LLM이 Tool Call을 리턴하면 자바 로직에서 switch-case나 Reflection으로 해당 메서드를 실행합니다.
실행 결과를 다시 LLM에게 던져 "다음 할 일"을 묻는 while 루프를 구현합니다.
[Agent Log 예시]
Thought: 사용자가 재고 확인과 메일을 요청했다. 먼저 재고부터 확인해야겠다.
Action: get_inventory_status("laptop") 호출
Observation: "재고 0개"
Thought: 재고가 없으니 메일을 보내야 한다. 메일 주소를 찾자.
Action: Contacts("구매팀") 호출
... (중략) ...
Final Answer: 재고가 없어 구매팀에 요청 메일을 발송했습니다.
비용 관리: 에이전트는 한 번의 질문에 여러 번 API를 호출하므로 토큰 소모가 큽니다.
신뢰성: 에이전트가 엉뚱한 도구를 호출하지 않도록 System Prompt에서 도구 사용 조건을 매우 엄격하게 정의해야 합니다.
기존 방식: 모델마다 API 연동 코드를 새로 짜야 함 (N:M 관계).
MCP 방식: 데이터 소스를 MCP 서버로 한 번만 만들면, 어떤 모델이든 MCP 클라이언트를 통해 즉시 연결 (1:N 관계).
MCP Host: 에이전트가 실행되는 환경 (예: Claude Desktop, IDE, 혹은 우리가 만든 커스텀 앱).
MCP Client: 에이전트 내부에서 MCP 서버와 대화하는 "통신 모듈".
MCP Server: 실제 데이터나 기술(Skills)을 가지고 있는 "제공자". (예: 로컬 파일 검색 서버, PostgreSQL 연결 서버).
Step 1: MCP 서버 구축 (Python/TypeScript)
복잡한 연동 로직 없이, mcp 라이브러리를 사용해 서버를 띄웁니다.
Python
# mcp_server.py
from mcp.server.fastmcp import FastMCP
# 1. 서버 이름 정의
mcp = FastMCP("Database_Agent_Server")
# 2. 에이전트가 쓸 도구(Skill) 등록
@mcp.tool()
def query_customer_db(customer_id: int) -> str:
"""고객 ID로 구매 이력을 조회합니다."""
# 실제 DB 연동 로직
return f"고객 {customer_id}: 최근 30일 내 아이폰 16 구매"
mcp.run()
Step 2: 에이전트(Client)에서 MCP 서버 연결
이제 에이전트 코드는 매우 단순해집니다. 서버 주소만 알려주면 됩니다.
Python
# agent_client.py (개념 코드)
from langchain_anthropic import ChatAnthropic
from mcp_client import MCPClient # MCP 연결용 라이브러리 가정
# 1. MCP 서버와 연결
with MCPClient("http://localhost:8000") as client:
# 2. 서버가 제공하는 도구(Skills)를 자동으로 가져옴
tools = client.get_available_tools()
# 3. 에이전트 생성
model = ChatAnthropic(model="claude-3-5-sonnet")
agent = create_react_agent(model, tools)
# 4. 실행
agent.invoke({"messages": [("user", "101번 고객님 구매 이력 좀 알려줘")]})
보안: 에이전트에게 전체 DB 권한을 주는 대신, MCP 서버가 허용한 "특정 함수"만 실행하도록 제한할 수 있습니다.
플러그인 생태계: 이미 공개된 수많은 MCP 서버(GitHub, Google Search, Slack 등)를 내 에이전트에 부품 끼우듯 바로 추가할 수 있습니다.
"우리가 만든 Skills를 MCP라는 표준으로 감싸서 배포하면, 어떤 Agent든 그 능력을 즉시 흡수하여 자율적으로 업무를 수행할 수 있게 됩니다. 이것이 현대 AI 플랫폼 개발의 표준입니다."