역대급 MCP 업데이트 설명: 레스토랑에 비유하여
요약
Model Context Protocol(MCP)의 최신 업데이트 내용을 레스토랑 비유를 통해 설명합니다. 기존의 세션 기반 방식에서 탈피하여, 모든 요청에 필요한 정보를 포함하는 방식으로 변경되어 서버리스 환경에서도 안정적인 연결이 가능해졌습니다.
핵심 포인트
- MCP는 AI 애플리케이션과 데이터/도구를 연결하는 개방형 표준(USB-C 포트)입니다.
- 최신 업데이트는 프로토콜에서 세션(session) 개념을 완전히 제거했습니다.
- 모든 요청에 메타데이터를 포함하여 서버리스 플랫폼과의 호환성을 높였습니다.
- 세션 의존성이 사라져 인스턴스 교체 시에도 연속적인 작업 수행이 가능합니다.
MCP 2026-07-28이 출시되었고, 세션은 사라졌습니다. 전체 이야기를 쉽게 풀어드립니다.
당신 시내에는 놀라운 웨이터가 있는 식당이 있습니다. 그는 모든 것을 기억합니다. 당신의 테이블 번호, 양파를 싫어하는 규칙, 친구와 계산을 나눠야 한다는 사실까지도요. 당신은 절대 같은 말을 반복할 필요가 없습니다. 정말 기분 좋은 경험입니다.
그런데 그 웨이터가 아프게 됩니다.
새로운 웨이터는 아무것도 모릅니다. 당신의 주문은 사라졌고, 양파를 싫어하는 규칙도 잊었습니다. 당신은 처음부터 다시 시작해야 하고, 짜증이 납니다. 식당 전체가 한 사람의 기억에 의존하고 있었던 것입니다.
이번 주까지 Model Context Protocol(MCP) 역시 정확히 그런 레스토랑과 같았습니다.
첫째: MCP란 무엇인가?
만약 MCP에 대해 들어본 적이 없다면, 공식 문서에서 제공하는 한 줄짜리 설명이 가장 빠른 시작점입니다. 바로 AI 애플리케이션을 위한 USB-C 포트입니다. 이는 개방형 표준(open standard)입니다. 어떤 회사에서 만들었든 관계없이 AI 애플리케이션(Claude, IDE, 챗봇, 에이전트 등)이 도구와 데이터에 동일한 방식으로 연결할 수 있게 해줍니다.
우리 식당의 비유로 설명하자면: 당신, 즉 고객은 클라이언트(AI 앱)입니다. 주방은 도구, 리소스(파일 및 데이터), 프롬프트를 제공하는 프로그램인 서버입니다. 메뉴판의 요리들은 도구입니다. 그리고 MCP 자체는 주문 시스템 그 자체입니다. 어떻게 요청할지, 주방이 어떻게 응답할지, 무언가 잘못되었을 때 무슨 일이 일어날지를 정의합니다.
7월 28일, MCP 팀은 2026-07-28 개정판 (버전을 지칭하는 그들의 용어)을 출시했습니다. 이들은 지난 5월에 출시 후보(release candidate)를 발표했을 때
그것 역시 동일한 약점을 가지고 있었습니다. 만약 그 인스턴스 하나가 충돌(crash)하면, 당신의 세션(session)도 함께 종료되었습니다. 로드 밸런서(load balancer, 레스토랑 입구의 호스트가 어떤 웨이터가 당신을 담당할지 결정하는 것처럼 요청을 여러 복사본에 분산하는 기계) 뒤에서 세 개의 인스턴스를 실행한다는 것은 밸런서가 "스티키(sticky)"해야 함을 의미했습니다. 즉, 호스트가 매번 당신을 동일한 웨이터에게 다시 보내야만 했습니다. 서버리스 플랫폼(serverless platforms, 요청이 도착할 때만 코드를 실행하는 AWS Lambda와 같은 클라우드 서비스)은 인스턴스를 끊임없이 시작하고 중단하기 때문에, 이 방식과는 잘 맞지 않았습니다.
새로운 버전은 프로토콜에서 세션을 완전히 제거했습니다. initialize는 사라졌습니다. 대신, 모든 요청이 서버에 필요한 모든 것을 작은 _meta 블록 안에 담아 전달합니다. 여기에는 당신이 사용하는 프로토콜 버전과 클라이언트가 무엇을 할 수 있는지에 대한 정보가 포함됩니다. 대화 내용이 아닌 기술적인 사실들만 담기며, 서버에 필요한 다른 모든 것은 일반적인 요청 파라미터(request parameters)로 전달됩니다.
레스토랑 용어로 설명하자면: 레스토랑이 카운터 서비스(counter-service) 매장으로 재개장한 것과 같습니다. 테이블 서비스(table service)는 사라졌습니다. 당신은 영수증을 손에 들고 카운터에서 주문합니다. 당신의 전체 주문 내역은 영수증에 인쇄되어 있으며, 어떤 계산원이라도 그 영수증을 집어 들어 서빙할 수 있습니다. 한 계산원이 퇴근하더라도, 다음 계산원이 동일한 영수증을 읽고 업무를 계속할 수 있습니다. 아무도 당신을 기억할 필요가 없습니다.
가장 간단한 전후 비교:
// 이전 (2025년 시대): 먼저 핸드셰이크(handshake)를 하고, 보호를 위해 세션을 생성
{
"jsonrpc": "2.0",
...
// 이후 (2026-07-28): 핸드셰이크 없음, 영수증이 모든 것을 담고 있음
{
"jsonrpc": "2.0",
...
공식 15초 애니메이션에서도 동일한 전후 차이를 보여줍니다. 왼쪽에서는 스티키 로드 밸런서가 세션 태그를 고정하여 모든 요청을 인스턴스 A로만 보내며, A가 죽으면 클라이언트도 함께 실패합니다. 오른쪽에서는 요청이 A, B, 또는 C로 번갈아 가며 전달되며(라운드 로빈, round-robin), A가 죽더라도 단순히 B와 C를 통해 계속 진행됩니다.
// Detect dark theme var iframe = document.getElementById('tweet-2082164250496348268-726'); if (document.body.className.includes('dark-theme')) { iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2082164250496348268&theme=dark" }
이것이 이번 릴리스의 가장 큰 승리입니다. 이제 MCP 서버를 서버리스 (serverless) 플랫폼이나 엣지 (edge) 플랫폼 (사용자와 가까운 소규모 서버)에 배포하거나, 일반적인 로드 밸런서 (load balancer) 뒤에서 확장할 수 있습니다.
문 앞의 안내 카드: server/discover
핸드셰이크 (handshake) 없이 서버가 무엇을 제공하는지 어떻게 알 수 있을까요? 새로운 호출 방식인 server/discover가 추가되었습니다. 2026-07-28부터 모든 서버는 이를 반드시 구현해야 합니다. 이 호출은 단 한 번의 응답으로 서버의 기능 (capabilities, 서버가 할 수 있는 일들의 목록)과 지원하는 프로토콜 버전 (protocol versions)을 반환합니다.
이전에는 식당에 들어가 자리에 앉은 뒤, 무엇을 알게 되기도 전에 웨이터와 계속해서 말을 주고받아야 했습니다. 이제는 문 앞에 놓인 카드가 이 지점이 어떤 종류의 서비스를 제공하는지 알려줍니다. 구체적인 요리 목록은 여전히 tools/list를 통해 요청해야 합니다. 이 카드에는 해당 정보가 얼마나 오랫동안 유효한지도 적혀 있습니다 (자세한 내용은 아래에서 설명).
진동벨: subscriptions/listen
사용자가 관심 있는 사항(리소스 업데이트, 도구 목록 변경, 프롬프트 목록 변경 등)을 서버에 알려주면, 서버는 사용자의 구독 ID (subscription ID)가 태그된 스트림 (stream)을 엽니다. 이것은 식당에서 건네주는 진동벨과 같습니다. 테이블 위에 조용히 놓여 있다가 주문 내용에 변화가 생길 때만 울립니다. 서버가 의도적으로 스트림을 닫고 싶을 때는 이제 적절한 작별 인사를 해야 합니다. 즉, 사용자의 구독 ID가 포함된 작은 "complete" 결과를 반환해야 합니다. 이렇게 함으로써 클라이언트는 정상적인 종료와 연결 끊김 (broken connection)의 차이를 알 수 있습니다.
여기 또 하나의 단순화가 숨어 있습니다. SSE (Server-Sent Events, 단방향 스트리밍 기술)의 재개 가능성(resumability), 즉 끊긴 스트림을 다시 시작하는 기능이 사라졌습니다. 이전 사양(spec)에서는 끊긴 스트림을 Last-Event-ID 헤더를 통해 재개할 수 있었는데, 이는 조용히 서버 측 메모리를 다시 요구했습니다. 이제 스트림이 끊기면, 그냥 새로운 ID와 함께 요청을 다시 보내기만 하면 됩니다. 만약 당신의 진동벨이 고장 난다면, 벨이 울리는 도중에 아무도 그것을 수리하지 않습니다. 대신 카운터에서 새 진동벨을 가져오는 것이죠. 단순하고 저렴합니다.
영수증에 적힌 질문: MRTR
이제 아무도 당신의 테이블로 올 수 없습니다. 주방의 질문을 전달했을 웨이터가 사라졌기 때문입니다. 대신 계산원이 당신의 영수증에 이렇게 적어둡니다: "어떤 소스로 드릴까요?" 당신은 답변이 적힌 동일한 영수증을 들고 카운터로 돌아갑니다. 그러면 어떤 계산원이든 그 영수증을 보고 주문을 완료할 수 있습니다. 이것이 이번 릴리스에서 가장 영리한 메커니즘이며, 사양(spec)에서는 **다중 왕복 요청 (Multi Round-Trip Requests, MRTR)**이라고 부릅니다.
이것이 해결하는 문제는 다음과 같습니다. 이전 프로토콜에서는 서버가 작업 중간에 클라이언트에게 요청을 다시 보낼 수 있었습니다. 예를 들어: "사용자에게 질문해 주세요" 또는 "이 내용을 당신의 모델로 실행해 주세요"와 같은 식입니다. 이는 양방향의 상태 유지 채널 (stateful channel, 상태 유지란 메시지 사이에도 서버가 당신을 기억해야 함을 의미함)이 필요한데, 이는 앞서 언급한 모든 내용과 충돌합니다.
대체 방식: 서버가 당신으로부터 무언가가 필요할 때, 서버는 당신을 호출하지 않습니다. 대신 resultType: "input_required"로 표시된 결과와 함께 현재 요청을 종료하며, 해당 결과 내에 질문 목록을 나열합니다. 그러면 클라이언트는 답변을 첨부하고, 서버가 보냈던 상태 토큰(영수증에 적힌 메모; 클라이언트는 이를 읽지 않고 그대로 다시 가져옵니다)을 포함하여 **동일한 요청을 재시도(retry)**합니다. 이를 통해 서버는 동일한 지점부터 작업을 계속할 수 있습니다.
이것이 바로 모든 결과가 이제 `
상태를 유지하지 않는 것(stateless)에는 비용이 따릅니다. 클라이언트가 "사용 가능한 도구가 무엇인가요?"와 같은 질문을 더 자주 반복하게 됩니다. 그래서 명세(spec)에 표준 캐싱 힌트(caching hints)가 추가되었습니다. 다섯 가지 결과(tools/list, prompts/list, resources/list, resources/read, resources/templates/list)와 server/discover는 이제 두 개의 필수 필드인 ttlMs와 cacheScope를 포함합니다.
ttlMs는 결과가 몇 밀리초(ms) 동안 유효한지를 나타냅니다. cacheScope는 누가 이를 재사용할 수 있는지를 나타냅니다. "private"는 동일하게 로그인된 사용자(동일한 인증 토큰)만 재사용할 수 있음을 의미하며, "public"은 누구나 재사용할 수 있음을 의미합니다. 이는 "10분 동안 유효함"이라는 메모가 붙은 메뉴판 사진과 같습니다. 이 사진은 문 옆의 공용 게시판에 고정되거나, 당신의 테이블에 개인적으로 놓여 있을 수 있습니다. 오직 최종적인 "complete" 결과만이 이러한 힌트를 포함하며, "input_required" 상태의 절반짜리 답변은 재사용을 위해 저장될 수 없습니다.
벽에 붙은 불만 사항 코드들
이제 레스토랑의 모든 지점 벽에 동일한 불만 사항 코드가 인쇄됩니다. 에러 코드(Error codes)의 번호가 재조정되었으며, 처음으로 어떤 번호가 누구의 소유인지에 대한 실제 규칙이 부여되었습니다. 헤더 불일치(header mismatch)는 -32020, 필수 클라이언트 기능(client capability) 누락은 -32021, 지원되지 않는 프로토콜 버전(unsupported protocol version)은 -32022입니다. -32020부터 -32099까지의 범위는 이제 명세(spec) 자체의 소유이며, 서버와 클라이언트는 이 범위 내에서 임의의 코드를 만들어내서는 안 됩니다. 이제 클라이언트는 에러 메시지를 읽고 추측하는 대신, 번호에 따라 즉각 반응할 수 있습니다.
오래된 뒷문이 닫히고 있습니다
이토록 큰 규모의 릴리스는 무언가와 작별을 고하기도 합니다:
- 클라이언트 기능인 Roots와 Sampling, 그리고 서버 유틸리티인 Logging은 더 이상 사용되지 않습니다 (deprecated는: 오늘날에도 작동하지만 제거될 예정임을 의미합니다). Logging 제어는
_meta로 이동했습니다. 즉,logging/setLevel을 호출하는 대신 요청별로logLevel을 설정해야 합니다. ping,logging/setLevel, 그리고 roots 목록 변경 알림이 제거됩니다.- 2024년의 기존 HTTP+SSE 전송 방식(transport는 메시지가 이동하는 방식)은 새로운 라이프사이클 정책에 따라 공식적으로 더 이상 사용되지 않습니다 (deprecated).
- Tasks가 코어(core)에서 확장(extension)으로 이동하여 코어 사양을 더 작게 유지합니다.
- OAuth 동적 클라이언트 등록(Dynamic Client Registration)은 더 이상 사용되지 않으며, Client ID Metadata Documents로 대체됩니다. OAuth를 건드리지 않는다면 이 항목은 건너뛰셔도 됩니다.
오래된 뒷문은 아직 한동안 열려 있을 것입니다. 왜냐하면 사양(spec)이 구형 서버와 통신하기 위한 신중한 규칙들을 정의하고 있기 때문입니다. 하지만 이제 그 표지판에는 이렇게 쓰여 있습니다: 메인 입구를 사용해 주십시오.
제가 이것을 작성하는 위치에서
짧은 솔직한 메모를 드립니다. 저는 몇 주 동안 이 마이그레이션 작업을 해왔습니다. 현재 Dart 팀의 MCP SDK (package:dart_mcp)를 이 버전으로 옮기고 있으며, 지금까지 dart-lang/ai에 5개의 병합된 풀 리퀘스트가 있었습니다. 작업 내용은 dart-lang/ai#162에서 공개적으로 추적할 수 있습니다. 최종 사양이 나왔을 때, 저는 이를 릴리스 후보(거의 최종 초안)와 줄 단위로 비교하여 보고서를 그곳에 올렸습니다. 따라서 위에 있는 모든 내용은 요약된 요약이 아니라 스키마 자체와 문서에서 나온 것입니다.
이것이 여러분에게 의미하는 바는
MCP 서버를 사용하는 앱을 구축한다면: SDK가 업데이트될 때까지 기다리십시오. 그런 다음 더 단순해진 모델을 즐기시면 됩니다. 올바르게 처리해야 할 핸드셰이크도, 잃어버릴 세션도 없습니다. 버전과 기능은 모든 요청과 함께 이동합니다.
MCP 서버를 작성한다면: 이 내용을 주방 벽에 붙여두세요. server/discover를 구현하세요. 모든 결과에 resultType을 포함하세요. 목록에 ttlMs와 cacheScope를 추가하고 결과를 읽으세요. 클라이언트에게 질문을 해야 했다면, input_required를 중심으로 그 흐름을 다시 설계하세요. 그 보상으로 서버는 마침내 어디에서나 실행될 수 있게 됩니다.
단순히 궁금한 것이라면: 실질적인 소식은 서버가 실행될 수 있는 위치의 자유입니다. 이전의 MCP 서버는 항상 켜져 있고 무언가를 기억하는 머신이 필요했습니다. 이제는 사용자 근처에서 수명이 짧은 함수 (short-lived functions)로 실행될 수 있으며, 일반적인 웹 서비스처럼 확장 (scale)될 수 있습니다.
또한 한꺼번에 변경된 사항들
존재를 알고 계셔야 할 몇 가지 작은 항목들입니다:
- OpenTelemetry 트레이스 키 (모니터링 ID)를 위해
_meta에 예약된 슬롯이 마련되었습니다. tools/list는 이제 안정적인 순서로 도구들을 반환해야 합니다.- 도구 파라미터는 이제 엄격한 명명 규칙 하에 새로운
x-mcp-header어노테이션 (annotation)을 사용하여 HTTP 헤더로 미러링될 수 있습니다. - 요청 시
clientInfo는 선택 사항이 되었으며,serverInfo는 이제 모든 결과의_meta에 포함되어 전달됩니다. - 네트워크를 통한 JSON Schema
$ref해석 (다른 서버에서 스키마 조각을 가져오는 것)은 이제 기본적으로 금지됩니다.
이 중 어느 것도 위의 이야기를 바꾸지는 않으며, 이 모든 것들은 삶을 더 예측 가능하게 만듭니다.
영수증을 주세요
한 웨이터의 완벽한 기억력에 의존하는 레스토랑은 그가 자리에 없는 날 전까지는 아주 멋진 곳일 수 있습니다. 모든 것을 영수증에 적는 레스토랑은 덜 낭만적일지 모르지만, 주문을 절대 놓치지 않으며, 아무런 문제 없이 백 개의 지점을 열 수 있습니다.
MCP는 바로 그 트레이드오프 (trade-off)를 수행했으며, 저는 그것이 탁월한 선택이었다고 생각합니다. 실제 코드에서 변화가 일어나는 것을 보고 싶다면, dart-lang/ai#162의 Dart 마이그레이션 내용을 하나씩 풀 리퀘스트 (pull request)를 확인하며 읽어보실 수 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기