본문으로 건너뛰기
김신건의 로그

[API Design] JSON-RPC vs gRPC vs REST: RPC 패턴 비교

· 수정 · 📖 약 2분 · 596자/단어 #rpc #json-rpc #grpc #rest #api-design
JSON-RPC, RPC, JSON-RPC 2.0, RPC vs REST

정의

RPC (Remote Procedure Call) = 원격 함수 호출 추상화. 세 가지 주요 형태:

  1. JSON-RPC: JSON 위 RPC. 가벼움.
  2. gRPC: Protobuf + HTTP/2.
  3. REST (RPC 스타일): POST /api/getUser 같이 동사 endpoint.

JSON-RPC 2.0 메시지

// 요청
{
  "jsonrpc": "2.0",
  "method": "getUser",
  "params": { "id": 42 },
  "id": 1
}

// 성공 응답
{
  "jsonrpc": "2.0",
  "result": { "id": 42, "name": "koa" },
  "id": 1
}

// 에러 응답
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32601,
    "message": "Method not found"
  },
  "id": 1
}

// 알림 (응답 없음)
{
  "jsonrpc": "2.0",
  "method": "log",
  "params": ["info", "user logged in"]
}

// Batch (배열)
[
  { "jsonrpc": "2.0", "method": "a", "id": 1 },
  { "jsonrpc": "2.0", "method": "b", "id": 2 }
]
표준 에러 코드의미
-32700Parse error
-32600Invalid request
-32601Method not found
-32602Invalid params
-32603Internal error
-32000 ~ -32099server error

gRPC: Protobuf + HTTP/2

Protocol Buffers (.proto) 로 서비스 정의:

syntax = "proto3";
package user;

service UserService {
  // Unary: 단일 요청, 단일 응답
  rpc GetUser(GetUserRequest) returns (User);
  // Server streaming: 단일 요청, 스트림 응답
  rpc ListUsers(ListUsersRequest) returns (stream User);
  // Client streaming: 스트림 요청, 단일 응답
  rpc CreateUsers(stream CreateUserRequest) returns (CreateUsersResponse);
  // Bidirectional streaming: 양방향 스트림
  rpc Chat(stream ChatMessage) returns (stream ChatMessage);
}

message GetUserRequest {
  string id = 1;
}

message User {
  string id = 1;
  string name = 2;
  string email = 3;
  int64 created_at = 4;
}

코드 생성:

# Go 코드 생성
protoc --go_out=. --go-grpc_out=. user.proto

# TypeScript 코드 생성
protoc-gen-ts --ts_out=. user.proto

# Python 코드 생성
python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. user.proto

gRPC 4가지 Streaming 모드

sequenceDiagram
    participant C as Client
    participant S as Server

    Note over C,S: 1. Unary (단방향 단일)
    C->>S: GetUser(id=42)
    S-->>C: User{id=42, name=koa}

    Note over C,S: 2. Server Streaming
    C->>S: ListUsers(filter=active)
    S-->>C: User{1}
    S-->>C: User{2}
    S-->>C: User{3}

    Note over C,S: 3. Client Streaming
    C->>S: CreateUser{name=a}
    C->>S: CreateUser{name=b}
    C->>S: CreateUser{name=c}
    S-->>C: CreateUsersResponse{count=3}

    Note over C,S: 4. Bidirectional Streaming
    C->>S: ChatMessage{text=hello}
    S-->>C: ChatMessage{text=hi}
    C->>S: ChatMessage{text=bye}
    S-->>C: ChatMessage{text=goodbye}
모드요청응답사용
Unary단일단일CRUD, 일반 API
Server Streaming단일스트림실시간 피드, 파일 다운로드
Client Streaming스트림단일파일 업로드, 배치 처리
Bidirectional스트림스트림실시간 채팅, 게임, 협업 도구

세 가지 RPC 비교

항목JSON-RPCgRPCREST (RPC 스타일)
Wire 포맷JSONProtobufJSON
전송HTTP/WS/TCPHTTP/2HTTP/1.1+
Schema옵션필수 (proto)OpenAPI
Streaming없음4 모드SSE/WS 별도
코드 생성옵션자동OpenAPI
크기 / 속도JSON 만큼수배 작고 빠름JSON
브라우저직접grpc-web 필요직접
Batch기본 지원없음없음

HTTP/2 와 gRPC

gRPC 는 HTTP/2 를 필수로 사용한다:

flowchart LR
    C[Client] -->|"HTTP/2 단일 연결"| S[Server]
    subgraph Connection[단일 TCP 연결]
        S1["Stream 1: GetUser(1)"]
        S2["Stream 2: GetUser(2)"]
        S3["Stream 3: ListUsers()"]
    end
    C --> Connection
HTTP/2 기능gRPC 에서의 효과
멀티플렉싱단일 연결 다중 RPC (Head-of-Line blocking 없음)
Header 압축 (HPACK)gRPC metadata 오버헤드 감소
Binary framingProtobuf 와 자연스럽게 결합
Server Pushstreaming 기반 구현

JSON-RPC 의 강점

flowchart LR
    A["가벼운 spec<br/>(1 페이지)"] --> Use1["블록체인 노드<br/>예: Ethereum"]
    A --> Use2["IDE to Language Server<br/>예: LSP"]
    A --> Use3[VSCode extension API]
    A --> Use4[debugger DAP]
표준RPC 토대
LSP (Language Server Protocol)JSON-RPC
DAP (Debug Adapter Protocol)JSON-RPC
MCP (Model Context Protocol)JSON-RPC
Ethereum JSON-RPCJSON-RPC
Bitcoin RPCJSON-RPC

IMPORTANT

JSON-RPC 는 VSCode / LSP / MCP / 블록체인de facto. 복잡도 vs gRPC 의 sweet spot.

언제 어떤 RPC?

flowchart TD
    Q1{브라우저 직접 호출?}
    Q1 -->|예| Q2{내부 API?}
    Q2 -->|"아니오 (외부)"| REST[REST]
    Q2 -->|예| Q3{"스트리밍 / typed?"}
    Q3 -->|typed 강력 필요| RestOpenAPI[REST + OpenAPI]
    Q3 -->|아니오| REST
    Q1 -->|"아니오 (server-to-server)"| Q4{성능 critical?}
    Q4 -->|예| GRPC[gRPC]
    Q4 -->|아니오| Q5{spec 단순함 중요?}
    Q5 -->|예| JsonRpc[JSON-RPC]
    Q5 -->|아니오| GRPC

grpc-web: 브라우저에서 gRPC

브라우저는 HTTP/2 raw frame 에 접근 불가 → grpc-web 프록시 필요:

flowchart LR
    Browser["Browser<br/>(grpc-web client)"] -->|"HTTP/1.1 or HTTP/2"| Proxy["Envoy Proxy<br/>(grpc-web to grpc)"]
    Proxy -->|"HTTP/2 gRPC"| Server[gRPC Server]
# Envoy 설정 (grpc-web 트랜스코딩)
filters:
  - name: envoy.filters.http.grpc_web
  - name: envoy.filters.http.cors

JSON-RPC TypeScript 구현 예시

type JsonRpcRequest = {
  jsonrpc: "2.0";
  method: string;
  params?: unknown;
  id: string | number;
};

type JsonRpcResponse<T> =
  | { jsonrpc: "2.0"; result: T; id: string | number }
  | { jsonrpc: "2.0"; error: { code: number; message: string }; id: string | number };

async function callRpc<T>(method: string, params?: unknown): Promise<T> {
  const response = await fetch("/rpc", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ jsonrpc: "2.0", method, params, id: Date.now() }),
  });
  const data: JsonRpcResponse<T> = await response.json();
  if ("error" in data) throw new Error(data.error.message);
  return data.result;
}

JSON-RPC 의 함정

WARNING

  1. method 이름 충돌 = namespace 없음. 큰 시스템에서 접두사 (user.get, order.create) 필요.
  2. HTTP status code 무관 = JSON-RPC 는 항상 200. error 는 body 의 error 객체. 모니터링 도구가 에러 못 잡음.
  3. Batch + notification 의 응답 매핑 = id 기반 매핑이 복잡. 잘못하면 응답이 섞임.
  4. 버전 관리 없음 = spec 자체에 버전 없음. 직접 method 이름에 v2 박는 식.
  5. gRPC 브라우저 제약 = grpc-web 프록시 없으면 브라우저에서 직접 호출 불가.

관련 위키

이 글의 용어 (4개)
[API Design] GraphQL: 단일 endpoint, N+1, persisted queriesapi-design
정의 GraphQL (Facebook, 2015) 은 클라이언트가 필요한 필드만 명시 하는 query language + 런타임. 단일 endpoint, typed schema,…
[API Design] OpenAPI / Swagger: 스펙, 코드 생성, contract testingapi-design
정의 OpenAPI Specification (OAS) 은 REST API 를 기술하는 YAML/JSON 형식. 옛 이름 Swagger. 2017 부터 OpenAPI Initia…
[API Design] REST API: 원칙, 자원 모델링, HATEOAS, 버전 관리api-design
정의 REST (Representational State Transfer) 는 Roy Fielding 의 2000년 박사논문에서 정립된 분산 시스템 아키텍처 스타일. HTTP 의…
[Network] gRPC: HTTP/2 + Protobuf, 4가지 streaming 패턴network
정의 gRPC 는 HTTP/2 위에서 Protobuf 직렬화 로 동작하는 고성능 RPC 프레임워크. Google 내부 Stubby 의 오픈소스 후계. 핵심 4가지: 1. Prot…

이 개념을 다룬 위키 페이지 (1)

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기