
에이전트 표면 (The Agent Surface)
요약
기존 소프트웨어 자산을 AI 에이전트가 네이티브하게 활용할 수 있도록 MCP(Model Context Protocol)를 일급 API 계층으로 도입해야 한다는 제안입니다. REST나 GraphQL처럼 에이전트 중심의 새로운 인터페이스 계층인 '에이전트 표면'의 필요성을 강조합니다.
핵심 포인트
- 기존 REST/SOAP API는 AI 에이전트가 소비하기에 부적합함
- 에이전트의 발견 가능성(Discoverability)을 위한 새로운 프로토콜 필요
- MCP를 활용해 그린필드 및 브라운필드 서비스에 에이전트 표면 구축 제안
- 기계가 읽을 수 있는 명세를 넘어 에이전트가 사용할 수 있는 인터페이스 지향
MCP를 일급 API 계층으로 — AI 네이티브 마이크로서비스를 위한 디자인 패턴, 그리고 기존 기업 자산을 AI 시대로 가져오기 위한 방법
오늘날 소프트웨어를 구축하는 모든 조직은, 그것을 명확히 표현했든 그렇지 않든 동일한 두 가지 질문에 직면합니다: 우리의 기존 애플리케이션을 어떻게 AI 세계와 연결할 것인가, 그리고 새로운 애플리케이션을 설계할 때 어떻게 첫날부터 AI-ready(AI 준비 완료) 상태가 되도록 만들 것인가?
이 문제의 브라운필드 (Brownfield, 기존 시스템 유지/확장) 버전은 기업 현대화 작업을 해본 사람이라면 누구나 익숙할 것입니다. 수십 년간 쌓여온 REST 서비스, SOAP 엔드포인트, 그리고 EJB 시대의 시스템들이 조직의 실제 비즈니스 역량을 보유하고 있지만, 그 중 어느 것도 AI 에이전트(AI agent)가 네이티브하게 소비할 수 없습니다. 그린필드 (Greenfield, 신규 구축) 버전은 더 미묘합니다. 우리는 여전히 인간과 기계만이 이 서비스를 호출할 유일한 소비자라고 가정하고 새로운 서비스를 설계하고 있습니다.
저는 두 질문에 대한 답이 동일하다고 생각하며, 그 답은 우리가 어떻게 여기까지 왔는지를 살펴보는 데 있다고 믿습니다.
누가 우리의 API를 소비하느냐에 따른 모든 주요 변화는, 그들을 지원하기 위한 프로토콜 계층을 만들어냈습니다. REST는 범용 클라이언트와 외부 통합을 지원하기 위해 등장했습니다. GraphQL은 UI가 고정된 리소스 표현 대신 유연하고 형태가 잡힌 쿼리 (shaped queries)를 필요로 했기 때문에 등장했습니다. gRPC는 서비스 간 통신 (service-to-service communication)이 대량의 트래픽에서 낮은 지연 시간 (low latency)과 엄격한 계약 (strict contracts)을 필요로 했기 때문에 등장했습니다. 각 사례에서 새로운 소비자 계층이 등장했고, 기존의 표면 (surfaces)이 그들에게 맞지 않았으며, 업계는 전용 계층으로 수렴했습니다.
이제 새로운 소비자 계층이 등장했습니다: 바로 **AI 에이전트 (AI agents)**입니다. 그리고 현재 우리는 다른 누군가를 위해 설계된 표면으로 그들을 지원하고 있습니다. 에이전트들은 취약한 글루 코드 (glue code)를 통해 REST API를 소비하고, 인간 개발자를 위해 작성된 OpenAPI 명세 (specs)를 역공학 (reverse-engineer)하며, 서비스가 실제로 무엇을 할 수 있는지에 대한 네이티브한 발견 가능성 (discoverability) 없이 작동하고 있습니다.
이 글의 제안은 명확합니다. 모든 서비스는 에이전트 표면 (Agent Surface)을 노출해야 합니다. 즉, 처음부터 구축되는 그린필드 (greenfield) 서비스에는 설계 단계부터 포함되어야 하고, 기존의 브라운필드 (brownfield) 서비스에는 점진적인 레이어로 추가되어야 하는, 동등한 지위를 가진 퍼스트 클래스 (first-class) API 표면으로서의 모델 컨텍스트 프로토콜 (Model Context Protocol, MCP) 레이어를 의미합니다. 하나의 패턴이 이 두 가지 질문 모두에 답을 제시합니다.
문제와 동인 (The Problem and the Forces)
디자인 패턴은 그것이 해결하는 동인 (forces)만큼만 가치가 있습니다. 그러므로 그 동인들을 명명해 보겠습니다.
발견 가능성 (Discoverability). 에이전트는 런타임 (runtime)에 추론할 수 있는 자기 기술적 (self-describing) 능력이 필요합니다. OpenAPI 명세는 엔드포인트(endpoint)를 _어떻게 호출하는지_를 문서화하지만, 에이전트가 언제 그리고 왜 호출해야 하는지는 표현하지 않습니다. 기계가 읽을 수 있는 것 (machine-readable)과 에이전트가 사용할 수 있는 것 (agent-usable) 사이의 간극은 실재하며, 오늘날 이 간극은 수작업으로 작성된 글루 코드 (glue code)로 채워져 있습니다. 기억력이 좋은 독자라면 런타임 자기 기술 (runtime self-description)이 REST 자체의 창립 약속이었던 HATEOAS였으며, 그것이 눈에 띄게 실패했다는 점을 지적할 것입니다. 진단이 중요합니다. 하이퍼미디어 (hypermedia)가 실패한 이유는 아이디어가 틀렸기 때문이 아니라, 그것에 따라 행동할 수 있는 소비자 (consumer)가 존재하지 않았기 때문입니다. 범용 클라이언트들은 링크를 무시했고 개발자들은 대신 문서를 읽었습니다. LLM 기반 에이전트는 런타임에 자기 기술적 표면을 실제로 읽고 발견한 내용에 따라 동작을 조정할 수 있는 최초의 소비자 계층입니다. 약속은 실패한 것이 아닙니다. 소비자가 나타나기 20년 전에 도착했을 뿐입니다.
입도 불일치 (Granularity mismatch). REST 엔드포인트는 리소스 (resource)를 모델링합니다. 에이전트는 도구 (tool)와 의도 (intent) 단위로 생각합니다. POST /policies 이후 PUT /policies/{id}/coverages, 그리고 다시 POST /policies/{id}/bind로 이어지는 과정은 하나의 에이전트 수준 의도("견적 확정 (bind a quote)")가 세 개의 리소스 작업으로 분산되어 있는 형태입니다. 가공되지 않은 엔드포인트를 에이전트에 그대로 노출하면, 에이전트는 호출할 때마다 귀하의 워크플로우 관례를 다시 발견해야 하며, 이는 비용이 많이 들고 때로는 부정확할 수도 있습니다.
보안 (Security). 에이전트는 새로운 종류의 호출자(caller)입니다. 자율적이고, 확률적이며, 그 어떤 UI도 하지 않을 방식으로 작업을 체이닝(chaining)할 수 있습니다. 인간의 세션과 결정론적 서비스 ID를 중심으로 구축된 API 보안 모델은 이러한 호출자를 염두에 두고 설계되지 않았습니다.
운영 액세스 (Operational access). 점점 더 우리는 에이전트가 단순히 우리의 서비스를 사용하는 것을 넘어, 서비스를 _운영(operate)_하기를 원합니다. 즉, 상태와 지표를 읽고, 성능 저하를 진단하며, 설정에 따라 조치를 취하는 것입니다. 관리 평면(management plane) 또한 에이전트 표면(agent surface)이 되어가고 있으며, 이는 비즈니스 평면(business plane)과는 매우 다른 리스크 프로필을 가집니다.
경제성 (Economics). 에이전트의 추론(reasoning)은 사용량에 따라 비용이 부과됩니다. 서비스가 인코딩하지 못한 모든 워크플로우 관례, 모든 장황한 스키마(schema), 에이전트가 시행착오를 통해 다시 발견해야 하는 모든 컨텍스트는 호출할 때마다, 모든 에이전트에 의해, 영구적으로 토큰(token) 비용으로 지불됩니다. 에이전트가 스스로 "파악하도록" 강요하는 표면은 일회성 설계 비용을 영구적인 런타임 비용으로 전환시킵니다.
레거시 현실 (Legacy reality). 대부분의 기업은 AI 시대를 위해 새로 작성되지 않을 대규모 Spring Boot 및 Jakarta EE 자산을 운영하고 있습니다. 재작성을 요구하는 패턴은 도입 단계에서부터 실패한 것이나 다름없습니다. 패턴은 반드시 _부가적(additive)_이어야 합니다.
패턴 (The Pattern)
이름: 에이전트 표면 (Agent Surface).
의도: REST, GraphQL, gRPC와 동등한 위치에서 자체적인 계약(contract), 생명주기(lifecycle), 보안 모델을 갖춘 전용 MCP 계층을 통해 서비스의 기능을 AI 에이전트에 네이티브하게 노출하는 것입니다.
구조: 하나의 서비스, 네 개의 표면
이 구조는 포트와 어댑터(ports-and-adapters) 사고방식의 직접적인 확장입니다. 서비스는 하나의 도메인 계층 — 즉, 하나의 비즈니스 기능 세트 — 를 가지며, 그 위에 서로 다른 소비자 클래스에 서비스를 제공하는 여러 프로토콜 어댑터(protocol adapters)를 가집니다.
| 표면 (Surface) | 소비자 (Consumer) | 최적화 대상 |
|---|---|---|
| REST | 일반 클라이언트, 외부 통합 | 보편성, 캐싱 가능성 |
| ... | ||
![]() |
이 중 어느 것도 생소한 것은 아닙니다. 우리는 이미 UI가 파트너 통합 (partner integration)과는 다른 표면 (surface)을 가질 자격이 있다는 점을 인정하고 있습니다. 여기서의 주장은 에이전트 (agents) 또한 동일한 위상을 가진 소비자 계층 (consumer class)이라는 것입니다. 즉, 에이전트는 그 요구사항이 충분히 독특하여 자체적인 어댑터 (adapter)를 가질 자격이 있으며, 그 어댑터는 즉흥적으로 만들어지는 것이 아니라 설계되어야 할 만큼 중요합니다.
이 표가 무엇이고 무엇이 아닌지에 대해 정확히 말하자면, 이것은 강제 사항이 아니라 소비자 계층 (consumer classes)을 설명하는 것입니다. 네 가지 표면을 모두 진정으로 필요로 하는 서비스는 거의 없으며, 세 가지를 동시에 사용하는 것도 실제로는 드문 일입니다. 서비스는 해당 표면을 사용할 소비자가 있을 때만 표면을 얻게 됩니다. 대부분은 두 개를 운영할 것입니다. 각 표면은 특정 유형의 호출자 (caller)를 위한 목적을 수행하기 위해 존재하며, 여기서의 주장은 그에 따라 매우 좁은 범위를 다룹니다. 에이전트가 이제 소비자 계층으로서 자격을 갖추었으므로, 에이전트가 당신의 소비자 중 하나라면 다른 누군가의 남은 조각이 아닌 설계된 표면을 제공받을 자격이 있다는 것입니다.
이를 인접한 BFA (Backend for Agents) 패턴과 구분할 가치가 있습니다. BFA는 BFF (Backend for Frontend)의 정신을 이어받아, MCP를 프로토콜로 사용하여 에이전트와 당신의 API 사이에 전용 중간 컴포넌트 (dedicated intermediary component)를 도입합니다. BFA는 실제 문제를 해결하지만, 또 다른 배포 가능한 요소 (deployable)를 통해 해결합니다. 즉, 자신이 소유하지 않은 기능들을 번역하여 보유하면서 구축, 버전 관리, 운영해야 할 서비스가 하나 더 늘어나는 것입니다. 에이전트 표면 (Agent Surface)은 반대의 입장을 취합니다. 에이전트 대면 계층 (agent-facing layer)은 서비스 '내부'의 다른 프로토콜 어댑터들과 함께 존재해야 하며, 도메인 로직 (domain logic)을 소유한 팀이 소유해야 합니다. 이 두 가지는 공존할 수 있습니다. 조직 수준의 BFA가 여러 서비스의 에이전트 표면들을 조합할 수 있습니다. 하지만 표면이 우선입니다. 중간 매개체 (intermediary)는 하위 서비스들이 노출하는 것만을 번역할 수 있기 때문입니다.
두 번째 반론에 대해서도 답변이 필요합니다: _MCP를 API 게이트웨이(API gateway)에 배치_하고, 그곳에 이미 등록된 OpenAPI 명세(specs)로부터 MCP를 생성하자는 것입니다. 게이트웨이 벤더들은 정확히 이 기능을 활발히 출시하고 있으며, 그 매력은 분명합니다. 즉각적인 전사적(estate-wide) 커버리지와 서비스 변경이 전혀 필요 없다는 점입니다. 하지만 게이트웨이에서의 자동 생성은 이 패턴이 피하고자 하는 실수들을 산업화합니다: 1:1 엔드포인트-도구 미러링 (규모가 커질 때 발생하는 입도(granularity)의 문제), 인간 개발자를 위해 작성된 스키마(schemas)를 에이전트에게 그대로 전달하는 것 (규모가 커질 때 발생하는 토큰 비용 문제), 그리고 의도 수준(intent-level)의 도구와 프롬프트(prompts)에 필요한 도메인 지식(domain knowledge)에 대한 접근 권한 부재가 그것입니다. 게이트웨이는 조직의 MCP 트래픽을 호스팅, 거버넌스(governing), 관찰(observing)하는 정당한 역할을 수행할 수 있지만, 자신이 소유하지 않은 도메인에 대한 표면(surface)을 _큐레이션(curate)_할 수는 없습니다. 생성(Generation)은 에이전트가 접근 가능한(agent-accessible) 서비스를 제공할 뿐입니다. 오직 설계(design)만이 에이전트가 사용 가능한(agent-usable) 서비스를 제공합니다.
2계층 모델 (The two-tier model)
에이전트 표면(Agent Surface) 내부에서, 저는 Spring 개발자들이 이미 잘 알고 있는 방식인 애플리케이션 엔드포인트(application endpoints)와 액추에이터 엔드포인트(actuator endpoints)의 분리를 반영한 분리 모델을 제안합니다.
1계층 — 애플리케이션 MCP (Application MCP). 서비스의 비즈니스 역량으로, 에이전트가 소비할 수 있는 도구(tools)와 리소스(resources)로 노출됩니다. 이는 여러분의 REST API에 대응하는 MCP 버전입니다: 정책 인용, 계정 조정, 참조 데이터 조회 등입니다.
2계층 — 관리 MCP (Management MCP). 액추에이터(actuator)에 대응하는 기능으로: 상태(health), 메트릭(metrics), 환경(environment), 그리고 운영 제어(operational controls)를 포함하며, 자산과 거래하는 것이 아니라 자산을 _운영(operate)_하는 것이 임무인 에이전트들을 위해 노출됩니다.
이러한 분리가 중요한 이유는 두 계층의 소비자(consumers), 위험 프로필(risk profiles), 그리고 인증 요구사항(authentication requirements)이 서로 다르기 때문입니다. 고객 대응 어시스턴트 에이전트는 1계층만, 오직 1계층만 보아야 합니다. SRE 진단 에이전트는 모든 쓰기 작업에 대한 감사(auditing)가 동반된 2계층이 필요합니다. 이 두 가지를 차별화되지 않은 하나의 도구 목록으로 합쳐버리면, 기술적으로는 여러분의 포드(pods)를 재시작할 수 있는 지원 챗봇(support chatbot)을 만들게 될 뿐입니다.
MCP 프리미티브 매핑 (Mapping the MCP primitives)
MCP는 서버에 세 가지 프리미티브를 제공하며, 이 패턴은 모든 것을 도구로 취급하기보다는 각각에 의도적인 역할을 할당합니다.
**도구(Tools)**는 모델이 제어하는 액션으로, 에이전트가 언제 이를 호출할지 결정합니다. 비즈니스 운영(Tier 1)과 스케일링이나 기능 플래그 토글 같은 관리 작업(Tier 2)이 여기에 해당됩니다. 대략적으로 말하면 POST와 PUT 요청입니다.
**리소스(Resources)**는 애플리케이션이 제어하는 읽기 전용 컨텍스트입니다. 이는 활용도가 낮은 프리미티브이며, 관리 평면(management plane)에 매우 적합합니다. 건강 상태(health), 메트릭(metrics), 환경 정보 등은 에이전트가 수행하는 것이 아니라 에이전트가 읽는 컨텍스트이기 때문입니다. 이는 비즈니스 측의 참조 데이터나 스키마에도 동일하게 적용됩니다. 대략적으로 말하면 부작용이 없는 GET 요청입니다. 여기서 즉시 도출되는 구체적인 설계 지침은 다음과 같습니다: 모든 엔드포인트를 도구로 자동 변환하는 것은 설계상의 결함(design smell)입니다. 도구/리소스 분리는 결정이며, 이는 에이전트가 서비스를 추론하는 방식을 형성합니다.
**프롬프트(Prompts)**는 놀라운 부분입니다. 서비스는 자체 도구를 올바르게 사용하는 방법에 대한 도메인 전문 지식—예: "성능 저하 진단", "계정 조정"—을 인코딩한 큐레이션된 상호 작용 레시피를 게시할 수 있습니다. 서비스가 단순히 기능을 노출하는 것이 아니라, 소비자에게 그 기능들을 어떻게 사용할지 가르치는 것입니다. 이를 _프로토콜 기능으로서의 실행 매뉴얼(runbooks as a protocol feature)_이라고 생각하십시오. 주류 API 표면 중 이와 동등한 것은 없습니다.
이 패턴에서 실제 문제를 해결하기 때문에 언급할 만한 두 가지 클라이언트 측 프리미티브가 있습니다. **샘플링(Sampling)**은 서버가 추론을 호출하는 에이전트의 LLM으로 위임할 수 있게 하여, 서비스가 모델 키를 소유하지 않고도 지능을 요청할 수 있도록 합니다. **요구(Elicitation)**는 서버가 작업 중간에 일시 정지하고 확인을 요청할 수 있게 하는데, 이는 Tier 2에 대한 가장 흔한 반론(
두 계층(tiers) 사이의 경계는 역할 기반 액세스(role-based access)입니다. 하지만 더 깊은 원칙은 에이전트가 익명의 도구 호출자(tool-callers)가 아니라, 제한된 권한(scoped permissions)을 가진 주체(principals)로서 인증된다는 점입니다.
이는 당연하게 들리지만, 실제로는 광범위하게 위반되고 있습니다. 오늘날 MCP 사용의 상당 부분은 "연결하는 누구든 도구를 사용할 수 있다"는 암시적 모델(implicit model)로 운영됩니다. 기업 환경(enterprise context)에서 이는 유지될 수 없는 방식입니다. 이 패턴은 에이전트의 정체성(identity)을 요구합니다. 즉, 연결되는 각 에이전트는 자신의 역할에 따라 무엇을 호출할 수 있는지뿐만 아니라, _무엇을 볼 수 있는지_를 결정하는 주체(principal)를 지녀야 합니다. 프로토콜은 이에 대한 구체적인 토대를 제공합니다. MCP의 권한 부여 명세(authorization specification)는 OAuth 2.1을 기반으로 하므로, 에이전트 주체(agent principals), 범위(scopes), 토큰 기반 역할(token-bound roles)은 기업이 이미 운영 중인 메커니즘에 직접 매핑됩니다. 여기서 새로운 인증 모델을 발명할 필요는 없습니다. 단지 하나를 적용하기로 결정하기만 하면 됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기