Back

MCP vs A2A: 2026년 AI 에이전트 프로토콜 완벽 가이드

2026년에 AI 에이전트를 만들고 있다면, 두 가지 약어를 끊임없이 들어봤을 거예요. MCPA2A. 그리고 이 둘에 대한 의견은 서로 완전 엇갈려요. "MCP가 AI의 USB-C다." "A2A가 MCP를 대체한다." "둘 다 써야 한다." "둘 다 아직 프로덕션에는 이르다."

실상은 이래요. 이 둘은 완전히 다른 문제를 풀어요. 이걸 혼동하는 게 지금 AI 엔지니어링에서 가장 흔한 실수 중 하나고요. MCP는 에이전트가 도구와 대화하는 방법이고, A2A는 에이전트끼리 대화하는 방법이에요. 여기서 헷갈리면 아키텍처 전체가 싸우기 시작해요.

이 글에서 두 프로토콜을 바닥부터 뜯어볼게요. 아키텍처, 메시지 흐름, 실제 코드, 실전 구현 패턴까지. 끝까지 읽으면 어떻게 조합하고 언제 뭘 쓰는지 확실히 감이 올 거예요.

아무도 생각 안 했던 두 가지 문제

MCP와 A2A가 존재하기 전에는, AI 도구 연동이 전부 하드코딩이었어요. Claude에 DB를 연결하고 싶으면? 직접 짜야 해요. GPT에 Slack을 연결하고 싶으면? 또 다른 커스텀 코드. 두 AI 에이전트를 화하게 하고 싶으면? 행운을 빌어요. 매번 바닥부터 만들어야 했거든요.

이게 두 가지 전혀 다른 연동 지옥을 만들었어요.

문제 1: 도구 연동 (MCP가 해결)
AI 제공자마다 외부 도구 연결 방식이 달랐어요. OpenAI는 function calling, Anthropic은 tool use, Google은 function declarations. JSON 스키마도, 응답 형식도, 에러 처리도 전부 달랐죠. Claude용 Postgres 커넥터를 만들어도 GPT에서는 상당 부분 다시 짜야 했어요.

문제 2: 에이전트 협업 (A2A가 해결)
멀티 에이전트 시스템을 만들기 시작하면서, 에이전트들이 서로를 발견하고, 능력을 확인하고, 작업을 넘기는 표준 방법이 없었어요. "리서치 에이전트"와 "작성 에이전트"가 있으면, 이 둘을 엮는 건 전부 애플리케이션 코드에서 수작업이었죠. 하나를 교체하면? 오케스트레이션 레이어 전체를 다시 짜야 했어요.

MCP와 A2A는 이 두 가지 별개의 문제에 각각 특화된 해답이에요. 이 분리를 이해하는 게 전부의 핵심이에요.

MCP: Model Context Protocol 깊이 파기

MCP가 뭔지 정확히

MCP(Model Context Protocol)는 Anthropic이 만들어서 2025년 12월에 Linux Foundation의 AAIF(Agentic AI Foundation)에 기증한 프로토콜이에요. AI 에이전트가 외부 도구, 데이터 소스, 서비스에 접속하는 방식을 표준화해요. AI 두뇌와 손 사이의 표준 인터페이스라고 생각하면 돼요.

2026년 2월 기준으로 MCP SDK 다운로드가 월 9,700만 회를 넘었고(Python + TypeScript 합산), Anthropic, OpenAI, Google, Microsoft, Amazon 등 메이저 AI 제공자 전부가 채택했어요.

아키텍처

MCP는 JSON-RPC 2.0을 와이어 포맷으로 쓰는 클라이언트-서버 아키텍처예요:

┌─────────────────────┐     JSON-RPC 2.0      ┌──────────────────┐
│                     │ ◄──────────────────►   │                  │
│   MCP 클라이언트     │     (stdio, SSE,       │   MCP 서버        │
│   (AI 에이전트/호스트)│      HTTP Streaming)   │   (도구 제공자)    │
│                     │                        │                  │
│  ┌───────────────┐  │                        │  ┌────────────┐  │
│  │ Claude/GPT/   │  │   요청:                │  │ Resources  │  │
│  │ Gemini/로컬   │──┼──► tools/call ────────►│  │ (데이터 읽기)│  │
│  │               │  │                        │  ├────────────┤  │
│  │               │◄─┼── 결과/에러 ◄─────────│  │ Tools      │  │
│  └───────────────┘  │                        │  │ (액션 실행) │  │
│                     │                        │  ├────────────┤  │
│                     │                        │  │ Prompts    │  │
│                     │                        │  │ (템플릿)    │  │
│                     │                        │  ├────────────┤  │
│                     │                        │  │ Sampling   │  │
│                     │                        │  │ (LLM 호출) │  │
│                     │                        │  └────────────┘  │
└─────────────────────┘                        └──────────────────┘

MCP 서버가 노출하는 4가지 기능:

  1. Resources: 읽기 전용 데이터 소스 (파일, DB 레코드, API 응답)
  2. Tools: 실행 가능한 액션 (쿼리 실행, 이메일 전송, 파일 생성)
  3. Prompts: 구조화된 인자를 가진 재사용 프롬프트 템플릿
  4. Sampling: 클라이언트에게 LLM 호출을 요청하는 기능 (역방향)

MCP 서버 만들기

DB 쿼리 기능을 제공하는 실전 MCP 서버를 TypeScript로 만들어 볼게요:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import postgres from "postgres"; const sql = postgres(process.env.DATABASE_URL!); const server = new McpServer({ name: "postgres-explorer", version: "1.0.0", }); // Resource: 사용 가능한 테이블 목록 server.resource( "tables", "postgres://tables", async (uri) => { const tables = await sql` SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' `; return { contents: [{ uri: uri.href, mimeType: "application/json", text: JSON.stringify(tables, null, 2), }], }; } ); // Tool: 읽기 전용 쿼리 실행 server.tool( "query", "Execute a read-only SQL query against the database", { sql: z.string().describe("The SQL query to execute (SELECT only)"), }, async ({ sql: query }) => { if (!query.trim().toUpperCase().startsWith("SELECT")) { return { content: [{ type: "text", text: "Error: Only SELECT queries allowed" }], isError: true, }; } const result = await sql.unsafe(query); return { content: [{ type: "text", text: JSON.stringify(result, null, 2), }], }; } ); // Tool: 테이블 스키마 조회 server.tool( "describe-table", "Get the schema of a specific table", { tableName: z.string().describe("Name of the table to describe"), }, async ({ tableName }) => { const columns = await sql` SELECT column_name, data_type, is_nullable, column_default FROM information_schema.columns WHERE table_name = ${tableName} AND table_schema = 'public' ORDER BY ordinal_position `; return { content: [{ type: "text", text: JSON.stringify(columns, null, 2), }], }; } ); const transport = new StdioServerTransport(); await server.connect(transport);

이 하나의 서버로 Claude Desktop, VS Code Copilot, Cursor 등 MCP 호환 클라이언트 어디서든 그대로 쓸 수 있어요. 수정 없이요.

트랜스포트

MCP는 세 가지 전송 방식을 지원해요:

트랜스포트용도동작 방식
stdio로컬 도구, CLI, 데스크톱 앱서버를 서브프로세스로 실행, stdin/stdout으로 메시지 교환
SSE원격 서버, 웹 기반HTTP + SSE로 서버→클라이언트 스트리밍
Streamable HTTP프로덕션 API, 클라우드 배포양방향 스트리밍 지원 HTTP (최신)

로컬 개발에서는 stdio가 가장 흔해요. Claude Desktop 같은 도구가 MCP 서버를 자식 프로세스로 실행하거든요. 프로덕션에서는 Streamable HTTP가 표준이 되어가고 있어요.

2026년 MCP 생태계

생태계가 폭발적으로 성장했어요. 2026년 3월 기준:

  • 공개 레지스트리에 5,800+개 MCP 서버 등록
  • GitHub, Slack, PostgreSQL, Google Drive, Stripe, AWS, Jira, Linear, Notion 등 공식 서버
  • Claude Desktop, VS Code, Cursor, Windsurf, Zed, JetBrains IDE에 빌트인 MCP 지원
  • 코드 실행 지원: MCP 서버가 데이터를 필터링/가공해서 LLM에 보내기 전에 처리 가능 → 토큰 소비 대폭 절감

"한 번 만들면 어디서든 쓴다"는 약속이 진짜로 작동하고 있어요.

A2A: Agent-to-Agent Protocol 깊이 파기

A2A가 뭔지 정확히

A2A(Agent-to-Agent)는 Google이 2025년 4월에 만들어서 같은 해 6월에 Linux Foundation에 기증한 프로토콜이에요. AI 에이전트들이 프레임워크나 벤더에 관계없이 서로를 발견하고, 소통하고, 협업하는 방식을 표준화해요. AI 에이전트들의 HTTP라고 생각하면 돼요.

빠르게 확산됐어요. IBM의 Agent Communication Protocol(ACP)이 2025년 8월에 A2A에 합류했고, 2025년 12월에는 Linux Foundation이 **AAIF(Agentic AI Foundation)**를 출범시켰어요. OpenAI, Anthropic, Google, Microsoft, AWS, Block이 공동 창립자로 참여했고, A2A와 MCP의 공동 거버넌스 체제가 됐어요. 2026년 2월까지 100개 이상의 기업이 지지 선언을 했고, 3중 AI 프로토콜 스택(MCP for 도구, A2A for 에이전트, WebMCP for 웹 접근)이 합의 아키텍처로 자리잡고 있어요.

아키텍처

A2A는 JSON-over-HTTP 방식의 클라이언트-리모트 아키텍처예요:

┌─────────────────────┐       HTTP/JSON         ┌──────────────────┐
│                     │ ◄────────────────────►   │                  │
│   클라이언트 에이전트  │                          │   리모트 에이전트   │
│   (오케스트레이터)    │                          │   (전문가)         │
│                     │    1. 발견                │                  │
│  "이거 해줘"        │ ──► GET /agent.json ────►│  Agent Card      │
│                     │ ◄── 능력 목록 ◄──────────│  (JSON 명세)     │
│                     │                          │                  │
│                     │    2. 태스크 라이프사이클   │                  │
│                     │ ──► tasks/send ──────────►│  작업 처리        │
│                     │ ◄── 상태 업데이트 ◄──────│  (비동기 가능)     │
│                     │                          │                  │
│                     │    3. 스트리밍            │                  │
│                     │ ──► tasks/sendSubscribe ─►│  실시간           │
│                     │ ◄── SSE 이벤트 ◄────────│  진행률            │
│                     │                          │                  │
│                     │    4. 아티팩트            │                  │
│                     │ ◄── 결과물 ◄────────────│  산출물            │
└─────────────────────┘                          └──────────────────┘

핵심 개념:

  1. Agent Card: 에이전트가 뭘 할 수 있는지 설명하는 JSON 명세 (/.well-known/agent.json에 배치)
  2. Tasks: 에이전트 간 작업 단위. 상태는 submitted, working, input-required, completed, failed, canceled
  3. Messages: 태스크 안에서 주고받는 메시지. 각각 하나 이상의 Part(텍스트, 파일, 데이터)로 구성
  4. Artifacts: 완료된 태스크가 뱉어내는 산출물
  5. Streaming: 오래 걸리는 태스크를 위한 SSE 실시간 업데이트

Agent Cards: 발견 메커니즘

Agent Card는 에이전트가 자기 능력을 광고하는 방법이에요. 잘 알려진 URL에 위치하며 이렇게 생겼어요:

{ "name": "Code Review Agent", "description": "보안 분석, 성능 프로파일링, 스타일 체크를 포함한 자동 코드 리뷰", "url": "https://code-review.example.com", "version": "2.1.0", "capabilities": { "streaming": true, "pushNotifications": true, "stateTransitionHistory": true }, "authentication": { "schemes": ["Bearer"], "credentials": "OAuth 2.0 token required" }, "defaultInputModes": ["text/plain", "application/json"], "defaultOutputModes": ["text/plain", "application/json"], "skills": [ { "id": "security-review", "name": "보안 취약점 스캔", "description": "OWASP Top 10 취약점, 의존성 위험, 시크릿 노출을 스캔", "tags": ["security", "OWASP", "vulnerability"] }, { "id": "performance-review", "name": "성능 분석", "description": "N+1 쿼리, 메모리 누수, 불필요한 리렌더를 분석", "tags": ["performance", "optimization", "memory"] } ] }

이게 왜 강력하냐면요. 클라이언트 에이전트가 리모트 에이전트의 능력을 자동으로 까보고, 적합한 녀석인지 판단하고, 사전 설정 없이 바로 일을 시킬 수 있으니까요.

태스크 라이프사이클

코드로 보는 완전한 A2A 상호작용:

// 클라이언트 에이전트: Code Review Agent에 태스크 전송 const response = await fetch("https://code-review.example.com/tasks/send", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer <token>", }, body: JSON.stringify({ jsonrpc: "2.0", method: "tasks/send", id: "task-001", params: { id: "review-pr-42", message: { role: "user", parts: [ { type: "text", text: "PR #42의 보안 취약점을 점검해줘. 인증 흐름을 수정하고 새 OAuth 프로바이더를 추가하는 PR이야.", }, { type: "data", data: { repository: "acme/backend", prNumber: 42, diffUrl: "https://github.com/acme/backend/pull/42.diff", }, }, ], }, }, }), }); const result = await response.json(); // result.result.status.state === "completed" // result.result.artifacts에 리뷰 결과가 들어 있음

장기 실행 태스크에는 스트리밍을 사용해요:

// SSE로 태스크 진행 상황을 스트리밍 eventSource.addEventListener("message", (event) => { const update = JSON.parse(event.data); switch (update.result.status.state) { case "working": console.log("에이전트 작업 중:", update.result.status.message); break; case "input-required": // 리모트 에이전트가 추가 정보를 요청 console.log("에이전트 입력 필요:", update.result.status.message); break; case "completed": console.log("리뷰 완료:", update.result.artifacts); break; } });

3중 프로토콜 스택

여기서 모든 퍼즐이 맞춰져요. 2026년 AI 시스템의 합의 아키텍처는 3중 스택이에요:

┌──────────────────────────────────────────────────────────┐
│                    애플리케이션                             │
├──────────────────────────────────────────────────────────┤
│                                                          │
│  Layer 3: A2A (에이전트 ↔ 에이전트)                        │
│  ┌──────────┐    ┌──────────┐    ┌──────────┐           │
│  │ 리서치    │◄──►│ 기획     │◄──►│ 실행     │           │
│  │ 에이전트  │    │ 에이전트  │    │ 에이전트  │           │
│  └─────┬────┘    └─────┬────┘    └─────┬────┘           │
│        │               │               │                 │
│  Layer 2: MCP (에이전트 ↔ 도구)                            │
│  ┌─────┴────┐    ┌─────┴────┐    ┌─────┴────┐           │
│  │ Bing     │    │ Calendar │    │ GitHub   │           │
│  │ Search   │    │ API      │    │ Actions  │           │
│  └──────────┘    └──────────┘    └──────────┘           │
│                                                          │
│  Layer 1: WebMCP (에이전트 ↔ 웹)                           │
│  ┌──────────────────────────────────────────┐            │
│  │ 에이전트를 위한 구조적 웹 접근               │            │
│  │ (llms.txt, 에이전트용 사이트맵)              │            │
│  └──────────────────────────────────────────┘            │
└──────────────────────────────────────────────────────────┘

Layer 1, WebMCP: 구조적 웹 접근이에요. 사이트가 llms.txt와 기계 판독 가능한 콘텐츠를 공개하는 방식인데, 아직 초기이지만 빠르게 퍼지고 있어요.

Layer 2, MCP: 에이전트가 도구를 쓰는 레이어예요. Postgres, GitHub, Slack 커넥터 같은 게 전부 MCP 서버로 동작해요.

Layer 3, A2A: 에이전트끼리 대화하는 레이어예요. 리서치 에이전트가 기획 에이전트한테 도움을 요청할 때 A2A가 조율해요. 각자 MCP 도구 연결은 유지하면서 동료끼리는 A2A로 소통하는 구조예요.

정면 비교표

항목MCPA2A
만든 곳Anthropic (2024.11)Google (2025.4)
관리 기관Linux Foundation AAIFLinux Foundation AAIF
용도에이전트 ↔ 도구 연동에이전트 ↔ 에이전트 통신
아키텍처클라이언트-서버클라이언트-리모트
와이어 포맷JSON-RPC 2.0JSON-RPC 2.0 over HTTP
발견 방식설정 기반Agent Cards (agent.json)
전송stdio, SSE, Streamable HTTPHTTP, SSE, 웹훅
인증서버 의존적OAuth 2.0 / Bearer 토큰
상태 관리세션 기반태스크 기반 상태 머신
핵심 단위도구 호출 / 리소스 읽기태스크 라이프사이클
SDK 다운로드~9,700만/월 (2026.2)빠르게 성장 중
서버 생태계5,800+ 공개 서버100+ 기업 채택
적합한 상황"이 에이전트에 X 도구 접근 권한 줘""에이전트 A가 에이전트 B에게 위임해"

겹치는 구간, 안 겹치는 구간

"이거 MCP로 해야 해? A2A로 해야 해?" 고민되는 회색지대가 있어요. 이 기준으로 판단하세요:

MCP를 쓸 때:

  • 결정론적 도구를 노출할 때 (DB, API, 파일 시스템)
  • 상호작용이 요청-응답 (함수 호출 → 결과 반환)
  • "서버"에 자체 지능이나 의사결정이 없을 때
  • 여러 AI 클라이언트와 호환이 필요할 때

A2A를 쓸 때:

  • 원격 시스템에 자체 AI 추론 능력이 있을 때
  • 태스크가 장시간이거나 왕복 협상이 필요할 때
  • 원격 시스템이 자율적 결정을 내려야 할 때
  • 에이전트 발견과 능력 매칭이 필요할 때

겹치는 영역:
문서를 요약하는 서비스가 있다고 해볼게요. MCP 도구일까요, A2A 에이전트일까요?

  • 고정 함수라면 (입력: 문서 → 출력: 요약) → MCP 서버
  • 맥락에 따라 어떻게 요약할지 결정하고, 확인 질문을 하고, 다른 서비스와 연계하면 → A2A 에이전트

판단 기준은 간단해요: MCP는 도구용, A2A는 동료용.

보안 고려사항

MCP 보안

MCP는 의도적으로 **인증에 무관(auth-agnostic)**해요. 프로토콜 자체가 인증 방식을 규정하지 않거든요:

// MCP 서버 구현자가 직접 접근 제어를 구현해야 해요 server.tool("query", "Run a database query", { sql: z.string() }, async ({ sql }, { authContext }) => { if (!authContext?.permissions?.includes("db:read")) { return { content: [{ type: "text", text: "Unauthorized" }], isError: true }; } const sanitized = await validateAndSanitize(sql); // ... } );

MCP 보안에서 주의할 점:

  • 도구 포이즈닝: 악성 MCP 서버가 LLM 동작을 조작하는 데이터를 반환할 수 있음
  • 과도한 권한: MCP 서버가 전체 DB나 파일 시스템에 접근하는 경우가 많음
  • 공급망 위험: 공개 레지스트리에서 MCP 서버를 설치하는 건 npm 패키지 까는 거랑 똑같아요. 뭘 하는 녀석인지 확인 필수
  • 도구를 통한 프롬프트 인젝션: MCP 도구가 반환하는 데이터에 주입된 명령이 포함될 수 있음

A2A 보안

A2A는 크로스 바운더리 통신용이라 빌트인 보안이 더 많아요:

주요 A2A 보안 포인트:

  • 에이전트 사칭: 에이전트가 없는 능력을 있다고 주장
  • 태스크 데이터 유출: 신뢰 경계를 넘어 에이전트 간 전달되는 민감한 데이터
  • 연쇄 공격: 손상된 에이전트가 A2A로 네트워크 내 다른 에이전트 공격
  • 감사 추적: 모든 에이전트 간 동작의 추적과 로깅 보장

실전 구현 패턴

패턴 1: 게이트웨이 에이전트

가장 흔한 패턴이에요. 게이트웨이 에이전트 하나가 사용자와 소통하면서 전문가 에이전트들에게 A2A로 위임:

사용자 ──► 게이트웨이 에이전트 ──A2A──► 전문가 에이전트 A
                               ──A2A──► 전문가 에이전트 B
                               ──A2A──► 전문가 에이전트 C
                         
각 전문가 에이전트는 MCP로 자체 도구에 접근

패턴 2: 파이프라인

에이전트가 순서대로 연결되어 결과를 전달:

입력 ──► 에이전트 1 ──A2A──► 에이전트 2 ──A2A──► 에이전트 3 ──► 출력
             │                  │                 │
           MCP               MCP               MCP

패턴 3: 메시

에이전트들이 필요에 따라 P2P로 통신:

에이전트 A ◄──A2A──► 에이전트 B
   ▲                     ▲
  A2A                  A2A
   ▼                     ▼
에이전트 C ◄──A2A──► 에이전트 D

패턴 4: MCP만 (A2A 불필요)

과도하게 복잡하게 만들지 마세요. 에이전트 하나에 도구만 필요하면 MCP만으로 충분해요:

단일 에이전트 ──MCP──► 도구 서버 1
              ──MCP──► 도구 서버 2
              ──MCP──► 도구 서버 3

대부분의 단일 에이전트 앱은 이 패턴이에요. Cursor + MCP 서버, Claude Desktop + 도구, VS Code + Copilot.

흔한 실수 5가지

실수 1: MCP로 충분한데 A2A 쓰기

"에이전트"라고 부르지만 실제로는 LLM 호출을 감싼 결정론적 함수면, A2A는 필요 없어요. MCP 서버가 더 단순하고, 빠르고, 이식성도 좋아요.

실수 2: MCP 서버 보안 무시

MCP 서버는 앱의 권한으로 실행돼요. 제한 없는 DB MCP 서버는 대참사가 기다리고 있어요.

실수 3: 자체 프로토콜 만들기

2026년에 에이전트 통신용 커스텀 HTTP 엔드포인트를 짜고 있다면, 기술 부채를 만들고 있는 거예요. 둘 다 성숙한 SDK와 생태계가 있어요.

실수 4: 둘을 혼동하기

"MCP 서버로 여러 에이전트를 조율하고 있어요"... 아뇨. 에이전트를 조율하는 거면 A2A가 맞아요.

실수 5: 너무 이른 멀티 에이전트 아키텍처

모든 시스템에 여러 에이전트가 필요한 건 아니에요. 에이전트 하나 + MCP 도구로 시작하세요. 진짜 에이전트 자율성이 필요한 이유가 있을 때 A2A를 추가하세요.

AAIF라는 변수

두 프로토콜 모두 2025년 12월에 출범한 Linux Foundation의 AAIF(Agentic AI Foundation) 아래에 있어요. OpenAI, Anthropic, Google, Microsoft, AWS, Block이 공동 창립자고요. 이게 중요한 이유:

  1. 중립적 거버넌스: Anthropic도 Google도 단독 통제권이 없음
  2. 수렴 압력: 두 프로토콜이 함께 진화. 더 긴밀한 통합 포인트 예상
  3. 기업 신뢰: 재단 거버넌스가 엔터프라이즈 채택을 안전하게 만듦
  4. 커뮤니티 주도: 기능 제안이 공개 RFC를 거침

결론

MCP와 A2A를 경쟁자로 보는 걸 그만두세요. 같은 스택의 계층이에요:

MCP는 에이전트에게 손을 줘요. A2A는 에이전트에게 동료를 줘요.

도구 접근이 필요한 단일 에이전트를 만든다면, MCP로 시작하세요. 성숙하고, 폭넓게 지원되고, 방대한 서버 생태계가 있어요.

전문 에이전트들이 서로를 발견하고, 태스크를 위임하고, 협업해야 하는 멀티 에이전트 시스템을 만든다면, A2A를 얹으세요.

2026년에 저지를 수 있는 최악의 실수는 또 다른 커스텀 연동 레이어를 만드는 거예요. 표준이 나왔어요. SDK가 프로덕션 수준이에요. 생태계가 폭발적으로 커지고 있어요.

스택 위에 만들고, 빠르게 배포하고, 진짜 중요한 문제로 넘어가세요.

AIMCPA2AagentsLLMprotocolarchitectureagentic-ai

관련 도구 둘러보기

Pockit의 무료 개발자 도구를 사용해 보세요