표준

[MCP] JSON-RPC란

Julie825 2025. 7. 29. 09:48

예전부터 gRPC를 두고 혁신이다, 아주 유용하다 라는 이야기는 많이 들어왔지만 뭘 위한 프로토콜인지 이해하기는 어려웠다.

이번에 MCP 프로토콜에 좀 더 단순한 형식의 JSON-RPC가 포함되면서 RPC의 유용함을 깨닫고 있다. 어떤 강점이 있는지, 어떤 스키마를 사용해야하는지 정리해보려고 한다.

 

1. RPC와 HTTP는 상반되는 개념이 아니다

JSON-RPC, gRPC는 모두 HTTP를 기반으로 동작할 수 있다.

HTTP POST를 사용해서 통신을 하며, body에 동작을 정의하는 식으로 활용한다.

 

그렇다고 HTTP 외의 통신방식을 사용할 수 없는 것은 아니다. 표준 입출력(stdio), WebSocket, raw TCP 스트림 등으로 JSON-RPC 메세지를 주고받을 수 있다.

 

RPC 프로토콜은 메세지를 기반으로 동작을 정의한다는 개념에서부터 시작한다.

2. RPC는 행동을, REST는 리소스를 표현한다.

RESTful한 API를 만든다고하면, 동작은 GET, POST 등 HTTP 메서드로 표현하고 자원을 path로 표현한다는 원칙을 지켜야한다.

RPC는 동작이 메세지 안에 담겨있다는 점에서 차이가 있다.

 

예를 들어 현재 GPT, Gemini, Sonnet 으로 프롬프트를 보낼수 있고, 현재 지원되는 모델을 골라 사용자의 요청을 처리해야한다고 생각해보자. RESTful API의 경우 총 4개의 API가 필요할 것이다.

GET  /models/list?is-working=true
POST /request/gpt 
POST /request/gemini
POST /request/sonnet

 

RPC를 사용하면 아래처럼 요청을 보낼 수 있다.

POST /model/jsonrpc

{
    "jsonrpc": "2.0",
    "method": "models/list",
    "params": {"is-working": true},
    "id": 1
}

// 프롬프트 요청
{
    "jsonrpc": "2.0",
    "method": "models/request",
    "params": {"model": "gpt", "gpt_param": {}},
    "id": 2
}

 

이렇게 행위(method 호출) 자체를 중심에 두고 요청을 설계하기 때문에, API 요청을 통해 외부 도구를 호출하거나 하는 경우 RESTful API보다 더 유연하게 사용할 수 있다.

다만 유연한만큼 문서화, 검증이 어렵기때문에 어느정도 인터페이스가 굳어진 내부 서비스에 한해서 RPC를 사용하는 것이 일반적이다.

 

3. JSON RPC의 스키마 - request, response, notification

HTTP 프로토콜에 헤더와 바디가 존재하듯이,

JSON‑RPC 2.0 스펙은 Request, Response, Notification, Batch 메시지 유형을 정의한다.

이중 MCP에서 필수로 사용되는 request, response, notification만 알아보자.

 

request

{
  "jsonrpc":"2.0",
  "id":1,
  "method":"methodName",
  "params": { /* 매개변수 */ }
}

- jsonrpc : 프로토콜의 버전을 의미한다.

- id : 요청을 식별하기 위해 쓰인다. 생략하면 notification으로 분류된다.

- method : 동작을 정의하기 위한 문자열. "rpc." 으로 시작하는건 예약어라서 쓸 수 없다.

- params : 파라미터. 생략가능하다.

 

response

{
  "jsonrpc":"2.0",
  "id":1,
  "result": { /* 정상 처리 결과 */ }
}
{
  "jsonrpc":"2.0",
  "id":1,
  "error": { "code": -32602, "message": "Invalid params" }
}

- jsonrpc : 프로토콜의 버전을 의미한다.

- id : 어떤 요청에 대한 응답인지 식별하기 위해 사용된다.

- result / error : 성공, 실패에 따라 둘 중 하나만 존재해야한다.

 

 

요청을 배열에 담아보내면 Batch로 인식된다. Batch 요청처리에 대한 규칙은 공식문서의 Batch 절을 참고하자.

 

notification

{
  "jsonrpc":"2.0",
  "method":"progress",
  "params": { "percent":50, "message":"Processing" }
}

요청에서 id 필드를 뺀 형태이다. 응답을 아예 받지 않겠다는 의미로 사용된다.

MCP에서는 서버가 클라이언트에게 변경사항을 알릴 때 유용하게 사용된다.

 

다만 notification을 지원한다고해서 JSON-RPC가 Stateful한 프로토콜은 아님을 기억하자. 프로토콜 자체는 당초 stateless한 프로토콜로 설계되었으나, MCP 기능의 특수성에 따라 양방향 연결을 유지하며 알림 기능을 사용하는 것에 가깝다.

 

4. RPC는 만능인가?

REST와 RPC는 마치 함수와 람다함수의 관계같다. RPC를 통해서 추상화 레벨을 높일 수 있다는 점에서 그렇다.

하지만 대부분의 경우 리소스 중심의 기능을 요구하는 경우가 많고, 기능이 자주 바뀌기에 검증이 어려워진다는 점은 치명적이다.

RPC중 가장 대중적이라고 여겨지는 gRPC가 필요한 케이스는 아래와 같다.

 

- 고성능 시스템이 필요한 경우
- 많은 양의 데이터 로드가 필요한 경우
- 실시간 또는 스트리밍 애플리케이션

 

아직은 MCP처럼 명백히 함수호출의 형태를 띄는 경우가 아니라면 REST를 대체할만한 프로토콜은 아닌 것 같다.


참고자료

- JSON-RPC 2.0 공식페이지

- AWS | gRPC와 REST