Overview
서비스 간 통신은 현대 소프트웨어 아키텍처에서 매우 중요한 요소이다. RESTful API는 여전히 널리 쓰이고 있지만, 더 높은 성능과 명확한 인터페이스 정의가 필요한 마이크로서비스 환경에서는 gRPC가 점점 각광받고 있다.
이 글에서는 gRPC의 기본 개념부터 REST와의 차이, 실전 예제, Kubernetes 배포, gRPC-Web 활용, 실제 사용 사례와 장단점까지 정리해보며, gRPC가 어떤 상황에서 효과적인 선택이 될 수 있는지 살펴본다.

gRPC란 무엇인가?
gRPC는 Google에서 개발한 오픈소스 RPC (Remote Procedure Call) 프레임워크로, 다음 특징을 가진다.
- HTTP/2 기반 통신
- Protocol Buffers(protobuf)를 사용한 인터페이스 정의
- 다양한 언어 지원 (Go, Java, Python, Node.js, C++, 등)
- 양방향 스트리밍, unary/bidirectional 통신 지원
즉, gRPC는 마치 원격 함수를 호출하는 것처럼 클라이언트-서버 간 통신을 처리하게 해준다.
REST와의 차이점
| 항목 | REST | gRPC |
| 전송 프로토콜 | HTTP 1.1 | HTTP/2 |
| 데이터 포맷 | JSON | Protocol Buffers |
| 성능 | 느린 파싱 속도 | 빠르고 작음 |
| 스트리밍 | 기본적으로 불가능 | 양방향 스트리밍 지원 |
| 브라우저 호환성 | 좋음 | 낮음 (gRPC-web 필요) |
| 언어 간 지원 | 제한적 (직접 작성) | protobuf 기반 자동 생성 |
gRPC 구조 요약
gRPC의 기본 구성 요소는 다음과 같다.
- .proto 파일: 서비스와 메시지 구조 정의
- gRPC 서버: 정의된 서비스를 실제로 구현
- gRPC 클라이언트: 자동 생성된 코드로 서버 호출
// hello.proto
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
gRPC의 장점
- 고성능: protobuf는 JSON보다 작고 빠르다. HTTP/2로 인해 멀티플렉싱과 헤더 압축도 지원
- 엄격한 타입 시스템: API 계약이 명확하고 자동으로 코드 생성됨
- 스트리밍: 서버 스트리밍, 클라이언트 스트리밍, 양방향 스트리밍 모두 가능
- 다양한 언어 지원: 마이크로서비스를 여러 언어로 구현할 때 유용
gRPC의 단점 및 주의점
- 브라우저 호환성이 낮음 → gRPC-Web 필요
- 초기 러닝 커브 존재: protobuf, 코드 생성, HTTP/2 설정 등
- 디버깅 불편: JSON이 아니기 때문에 디버깅과 로그 확인이 불편할 수 있음
도입에 적합한 환경은?
- 내부 서비스 통신용 API (특히 마이크로서비스 간)
- 고성능이 중요한 환경 (ML 서빙, 실시간 처리 등)
- 양방향 통신이 필요한 경우 (채팅, 스트리밍, IoT)
반면, 외부 클라이언트(브라우저 포함)와의 API는 REST/GraphQL이 더 편리할 수 있다.
실전 예제: Node.js 기반 gRPC 서버와 클라이언트
1. proto 정의 (greet.proto)
syntax = "proto3";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
2. 서버 코드 (Node.js)
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDef = protoLoader.loadSync("greet.proto");
const grpcObject = grpc.loadPackageDefinition(packageDef);
const greeter = grpcObject.Greeter;
function sayHello(call, callback) {
callback(null, { message: `Hello, ${call.request.name}` });
}
const server = new grpc.Server();
server.addService(greeter.service, { SayHello: sayHello });
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => {
server.start();
});
3. 클라이언트 코드 (Node.js)
const client = new greeter('localhost:50051', grpc.credentials.createInsecure());
client.SayHello({ name: 'Somaz' }, (err, response) => {
console.log(response.message);
});
gRPC + Kubernetes 배포
1. Dockerfile 작성
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "server.js"]
2. Deployment & Service
apiVersion: apps/v1
kind: Deployment
metadata:
name: grpc-server
spec:
replicas: 1
selector:
matchLabels:
app: grpc
template:
metadata:
labels:
app: grpc
spec:
containers:
- name: grpc-server
image: your-registry/grpc-server:latest
ports:
- containerPort: 50051
---
apiVersion: v1
kind: Service
metadata:
name: grpc-service
spec:
selector:
app: grpc
ports:
- name: grpc
port: 50051
targetPort: 50051
- gRPC 클라이언트는 동일 네트워크에서 `grpc-service:50051` 로 접근 가능
gRPC-Web 사용법 (브라우저 클라이언트)
브라우저는 HTTP/2 기반의 바이너리 전송을 직접 지원하지 않기 때문에 gRPC-Web이라는 브리지가 필요하다.
1. `envoy.yaml` 설정
static_resources:
listeners:
- address:
socket_address: { address: 0.0.0.0, port_value: 8080 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
codec_type: AUTO
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: grpc_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route: { cluster: grpc_server }
http_filters:
- name: envoy.filters.http.grpc_web
- name: envoy.filters.http.router
clusters:
- name: grpc_server
connect_timeout: 0.25s
type: LOGICAL_DNS
http2_protocol_options: {}
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: grpc_server
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: grpc-service, port_value: 50051 }
2. 클라이언트 코드 (gRPC-Web + JavaScript)
import { GreeterClient } from './proto/GreetServiceClientPb';
import { HelloRequest } from './proto/greet_pb';
const client = new GreeterClient('http://localhost:8080');
const request = new HelloRequest();
request.setName("Somaz");
client.sayHello(request, {}, (err, response) => {
console.log(response.getMessage());
});
마무리
gRPC는 단순히 “REST보다 빠르다”는 이유만으로 선택해야 하는 기술은 아니다.
명확한 API 정의, 멀티 언어 지원, 고성능 스트리밍 처리가 필요한 내부 마이크로서비스 통신에 특히 효과적인 도구이다.
조금의 학습 곡선을 넘는다면, gRPC는 당신의 분산 시스템을 더 효율적이고 안정적으로 만들어 줄 수 있는 강력한 무기가 될 수 있다.
- gRPC는 REST보다 빠르고, 구조적으로 더 강력하다.
- Kubernetes 환경에 적합하며, gRPC-Web을 통해 프론트엔드와도 연결 가능하다.
- 다만 디버깅, 브라우저 호환성 등 고려할 점도 존재한다.
Reference
'IaC > Service Mesh' 카테고리의 다른 글
| Istio 설치 및 실습 (0) | 2024.02.13 |
|---|---|
| Istio란? (0) | 2023.04.15 |
| Service Mesh vs Api Gateway (0) | 2023.03.08 |