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

[Network] gRPC: HTTP/2 + Protobuf, 4가지 streaming 패턴

· 수정 · 📖 약 2분 · 757자/단어 #grpc #rpc #network #backend #protobuf #http2
gRPC, Protocol Buffers, Protobuf, gRPC streaming, unary RPC, bidirectional streaming, grpc-web

정의

gRPCHTTP/2 위에서 Protobuf 직렬화 로 동작하는 고성능 RPC 프레임워크. Google 내부 Stubby 의 오픈소스 후계.

핵심 4가지:

  1. Protobuf: IDL + binary 직렬화 (JSON 대비 수배 작고 빠름)
  2. HTTP/2: multiplexing + binary framing
  3. Streaming 4종: unary, server-stream, client-stream, bidi
  4. Code generation: .proto → 다국어 stub 자동 생성

Proto 정의

syntax = "proto3";
package shop.v1;

service Shop {
  // Unary: 1 req → 1 res
  rpc GetItem(GetItemRequest) returns (Item);

  // Server streaming: 1 req → N res
  rpc ListItems(ListRequest) returns (stream Item);

  // Client streaming: N req → 1 res
  rpc UploadEvents(stream Event) returns (UploadAck);

  // Bidirectional: N req ↔ N res
  rpc Chat(stream Message) returns (stream Message);
}

message Item {
  string id = 1;
  string name = 2;
  int32 price_cents = 3;
}

4가지 Streaming 패턴

flowchart TB
    subgraph Unary["Unary RPC"]
        U1[Client] -->|1 request| U2[Server]
        U2 -->|1 response| U1
    end
    subgraph ServerStream["Server Streaming"]
        S1[Client] -->|1 request| S2[Server]
        S2 -->|stream of N| S1
    end
    subgraph ClientStream["Client Streaming"]
        C1[Client] -->|stream of N| C2[Server]
        C2 -->|1 response| C1
    end
    subgraph BiDi["Bidirectional Streaming"]
        B1[Client] -->|stream of N| B2[Server]
        B2 -->|stream of M| B1
    end
패턴사용
Unary일반 API
Server stream라이브 피드, log tail, 실시간 시세
Client stream파일 업로드, 이벤트 일괄 전송
Bidi stream채팅, 게임, 협업

HTTP/2 위 동작

:method = POST
:scheme = https
:path = /shop.v1.Shop/GetItem
:authority = api.example.com
content-type = application/grpc
grpc-encoding = gzip
grpc-accept-encoding = identity,deflate,gzip
grpc-timeout = 1S

<protobuf-encoded body>

각 RPC = HTTP/2 stream 하나. Trailersgrpc-status, grpc-message 전달.

Status Code

코드의미
0 OK성공
1 CANCELLED클라이언트가 cancel
2 UNKNOWN정체불명 에러
3 INVALID_ARGUMENT입력 오류
4 DEADLINE_EXCEEDEDtimeout
5 NOT_FOUND리소스 없음
6 ALREADY_EXISTS중복
7 PERMISSION_DENIED권한
8 RESOURCE_EXHAUSTEDquota 초과
9 FAILED_PRECONDITION사전조건 위배
10 ABORTED동시성 충돌
11 OUT_OF_RANGE범위 외
12 UNIMPLEMENTED구현 안됨
13 INTERNAL내부 에러
14 UNAVAILABLE일시 불가, retry 권장
15 DATA_LOSS손실
16 UNAUTHENTICATED인증 실패

IMPORTANT

UNAVAILABLE (14) 만 retry 안전. DEADLINE_EXCEEDED (4)side effect 가 발생했을 수 있어 idempotent operation 만 retry.

Deadline (timeout)

# Python
response = stub.GetItem(req, timeout=1.0)  # 1초

# 또는 metadata
metadata = (("grpc-timeout", "1S"),)

클라이언트의 deadline 은 서버에 전파 (header). 서버가 더 깊은 RPC 를 부르면 남은 deadline 만 전달. 분산 timeout chaining.

gRPC vs REST

항목gRPCREST
Wire 포맷Binary (Protobuf)Text (JSON)
크기수배 작음크다
SchemaIDL 필수옵션 (OpenAPI)
Streaming4 모드SSE / WebSocket 별도
브라우저 직접 호출grpc-web 필요기본 지원
Debugging도구 필요curl 가능
캐싱직접 구현HTTP cache
Mobile / IoT유리OK

내부 microservice 통신 → gRPC. 외부 public API → REST/GraphQL.

gRPC-Web

브라우저는 HTTP/2 trailer 미지원 → Envoy / proxygRPC ↔ gRPC-Web 변환:

flowchart LR
    Browser -->|gRPC-Web<br/>over HTTP/1.1| Envoy
    Envoy -->|gRPC<br/>over HTTP/2| Backend

흔한 함정

WARNING

  1. Field number 재사용 = proto 의 tag 번호wire format 의 identity. 한 번 쓴 번호 영구히 reserved.
  2. required 필드 = proto2 의 legacy. proto3 는 모든 필드가 optional 류. required 사용 금지.
  3. string vs bytes = string 은 UTF-8 검증. binary 데이터는 bytes.
  4. stream 의 완료 표시 = 클라이언트 stream 은 반드시 half-close (closeSend) 해야 서버가 finalize.

Interceptor (미들웨어)

# Python: 서버 interceptor, 인증 검사
class AuthInterceptor(grpc.ServerInterceptor):
    def intercept_service(self, continuation, handler_call_details):
        metadata = dict(handler_call_details.invocation_metadata)
        if metadata.get('authorization') != 'Bearer valid-token':
            def deny(request, context):
                context.abort(grpc.StatusCode.UNAUTHENTICATED, 'Invalid token')
            return grpc.unary_unary_rpc_method_handler(deny)
        return continuation(handler_call_details)

Interceptor = gRPC 의 미들웨어. 인증, 로깅, 메트릭, retry 등 횡단 관심사 처리. 체인 가능.

Metadata (Header 역할)

# 클라이언트: metadata 전송
metadata = [
    ('request-id', 'abc-123'),
    ('x-tenant-id', 'org-1'),
]
response = stub.GetItem(req, metadata=metadata)

# 서버: metadata 수신
def GetItem(self, request, context):
    md = dict(context.invocation_metadata())
    tenant = md.get('x-tenant-id')
    ...

Metadata = HTTP 헤더 역할. 요청마다 전달되며 Interceptor 에서도 읽기 가능.

Health Check Protocol

// grpc.health.v1.Health 표준
service Health {
  rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
  rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
}
# K8s 1.24+ 네이티브 gRPC probe
livenessProbe:
  grpc:
    port: 50051
    service: shop.v1.Shop
  initialDelaySeconds: 5
grpc_health_probe -addr=:50051 -service=shop.v1.Shop

Load Balancing

flowchart LR
    Client --> Envoy["Envoy / L7 LB"]
    Envoy -->|round-robin| B1[Backend 1]
    Envoy -->|round-robin| B2[Backend 2]
    Envoy -->|round-robin| B3[Backend 3]

HTTP/2 multiplexing 때문에 TCP 레벨 (L4) LB 는 단일 서버로 몰림. L7 LB 또는 클라이언트 사이드 LB 필요.

방식설명사용
클라이언트 사이드DNS 조회 후 round-robingRPC core 기본 지원
Envoy proxysidecar 패턴, Istio서비스 메시 환경
K8s HeadlessServicePod IP 직접 노출클라이언트 LB 와 조합

ConnectRPC (gRPC 대안)

ConnectRPC (buf.build) = HTTP/1.1, HTTP/2 모두 지원. curl 로 테스트 가능. gRPC 호환. 브라우저 직접 호출 (grpc-web proxy 불필요). 2026 시점 생태계 성장 중.

관련 위키

이 글의 용어 (6개)
[API Design] GraphQL: 단일 endpoint, N+1, persisted queriesapi-design
정의 GraphQL (Facebook, 2015) 은 클라이언트가 필요한 필드만 명시 하는 query language + 런타임. 단일 endpoint, typed schema,…
[API Design] JSON-RPC vs gRPC vs REST: RPC 패턴 비교api-design
정의 RPC (Remote Procedure Call) = 원격 함수 호출 추상화. 세 가지 주요 형태: 1. JSON-RPC: JSON 위 RPC. 가벼움. 2. gRPC: P…
[API Design] REST API: 원칙, 자원 모델링, HATEOAS, 버전 관리api-design
정의 REST (Representational State Transfer) 는 Roy Fielding 의 2000년 박사논문에서 정립된 분산 시스템 아키텍처 스타일. HTTP 의…
[Network] HTTP/2: multiplexing, HPACK, server push의 종말network
정의 HTTP/2 (2015, RFC 9113) 는 HTTP/1.1 의 문법은 유지하되 전송을 바이너리 + 멀티플렉싱 으로 바꾼다. Head-of-Line Blocking (HT…
[Network] Load Balancer: L4 vs L7, 알고리즘, sticky sessionnetwork
정의 Load Balancer 는 트래픽을 여러 백엔드로 분산 하는 인프라. 수평 확장 + 가용성 + 무중단 배포 의 토대. L4 vs L7 | 구분 | L4 (Transport…
[Pattern] Microservices vs Monolith: 언제 분리, 언제 통합distributed-systems
정의 | - | Monolith | Modular Monolith | Microservices | |---|---|---|---| | 배포 단위 | 1개 | 1개 (모듈 명확) …

💬 댓글

사이트 검색 / 명령어

검색

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