gRPC
"A high-performance, open source, universal RPC framework that can run in any environment."
— gRPC 공식 웹사이트
인간이 읽을 수 있는 텍스트(JSON) 대신 컴퓨터가 미치도록 좋아하는 이진 스트림으로 데이터를 우겨 넣어 통신 성능을 쥐어짜 내는 인색한 고성능 매니아. 프론트엔드와 직접 통신하기에는 너무나도 불친절하여 결국 백엔드 마이크로서비스들끼리 뒷골목에서 은밀하게 속닥거리는 '그들만의 리그' 통신망으로 굳혀졌다
1. 개요
gRPC는 구글이 2015년 개발하여 2016년 공식 릴리스한 오픈소스 고성능 원격 프로시저 호출(RPC) 프레임워크다. 클라이언트가 원격 서버에 있는 메서드를 마치 로컬 컴퓨터의 함수 호출하듯 자연스럽게 실행할 수 있게 해준다. 네트워크 전송 매체로 차세대 웹 프로토콜인 HTTP/2를 강제 적용하고, 데이터 규격으로 텍스트 기반의 JSON이나 XML 대신 초강력 이진 압축 규격인 프로토콜 버퍼(Protocol Buffers)를 채택함으로써, REST API가 가졌던 직렬화 및 대역폭 낭비 문제를 완전히 박살 낸 고성능 통신의 표준이다.(...)
2. HTTP/2 멀티플렉싱과 프로토콜 버퍼의 이진 혁명
2.1. REST API의 무거운 짐을 벗어던지다
REST API는 누구나 쉽게 읽고 쓸 수 있는 JSON을 데이터 포맷으로 활용하지만, 텍스트 파일 특성상 데이터의 덩치가 너무 크고 컴퓨터가 이를 해석(파싱)하는 데 적지 않은 CPU 자원을 소모한다. 또한 매번 연결을 맺고 끊는 HTTP/1.1 프로토콜 특성상 통신 지연(Latency)이 발생할 수밖에 없었다.
gRPC는 이 문제를 완벽하게 우회했다.
- Protocol Buffers의 마법: IDL(인터페이스 정의 언어)인
.proto파일에 스키마를 미리 정의해 두고 컴파일하면, 텍스트가 아닌 숫자로 매핑된 극도의 압축 이진 데이터(Binary)가 만들어진다. 텍스트 대비 전송 크기가 최대 10분의 1 이하로 줄어들어 대역폭을 극단적으로 아낀다. - HTTP/2의 멀티플렉싱: 단 하나의 TCP 연결 위에서 수십~수백 개의 데이터 스트림을 순서 보장 없이 병렬 전송하는 멀티플렉싱(Multiplexing) 기술을 통해, 네트워크 자원 소모를 최소화하고 응답 속도를 광속 수준으로 끌어올린다.(...)
이러한 구조적 이점 덕분에 서비스 간에 기가바이트 단위의 초고속 데이터 통신이 실시간으로 왕복하는 마이크로서비스 아키텍처 내부 통신의 일등 공신으로 지목받는다.
3. 4가지 통신 모드와 백엔드 MSA의 심장
3.1. 단순한 요청-응답을 넘어선 스트리밍의 향연
gRPC는 기존 REST API가 흉내 내기 힘들었던 다양한 형태의 양방향 스트리밍 통신 모드를 네이티브하게 지원한다.
- Unary (단방향 RPC): 클라이언트가 한 번 요청하면 서버가 한 번 응답하는 가장 기본적인 통신 구조.
- Server Streaming (서버 스트리밍): 클라이언트의 요청 한 번에, 서버가 마치 유튜브 비디오 스트리밍하듯 끊임없이 데이터를 조각조각 밀어주는 방식.
- Client Streaming (클라이언트 스트리밍): 클라이언트가 서버에 데이터를 여러 번 걸쳐 스트리밍으로 쏟아붓고, 서버는 최종 처리가 끝난 뒤 한 번만 응답하는 방식.1
- Bidirectional Streaming (양방향 스트리밍): 서버와 클라이언트가 서로 완전히 연결된 파이프라인을 뚫어두고 동시에 데이터를 실시간으로 소통하는 방식.
3.2. 프론트엔드 장벽과 gRPC-Web의 타협
gRPC는 HTTP/2 하단의 로우 레벨 영역(Trailer, Frame 제어)에 강하게 의존하고 있기 때문에, 일반적인 크롬이나 사파리 같은 웹 브라우저 단독으로는 직접 호출이 어렵다는 태생적 한계가 존재한다. 이 때문에 프론트엔드와 통신할 때는 보통 Envoy 프록시 같은 게이트웨이를 중간에 두고 gRPC-Web 어댑터를 거쳐 통신하는 귀찮은 우회책을 적용해야 한다. 결국 현업에서는 브라우저-서버 구간은 대중적인 REST나 GraphQL을 쓰고, 서버-서버(MSA 내부) 구간은 gRPC로 촘촘히 엮는 '이원화 인프라'를 주로 선호한다.2
4. 관련 밈 및 드립
4.1. 이진 데이터의 침묵 (디버깅 지옥)
gRPC 통신 장애가 터졌을 때, 개발자들이 겪는 황망함을 뜻하는 밈.
REST API라면 Wireshark나 브라우저 개발자 도구를 켜서 '아, id가 null이라 터졌구나!' 하고 바로 원인을 파악할 수 있다. 하지만 gRPC는 암호 같은 바이너리 패킷 0a 0f 08 96 ...만 눈앞에 둥둥 떠다니기 때문에 눈으로는 원인을 식별하는 것이 아예 불가능하다. 결국 백엔드 개발자들은 Wireshark에 gRPC 디코더 플러그인을 수동으로 깔거나, gRPC 전용 디버깅 클라이언트인 grpcurl을 터미널에서 연타하며 한숨을 쉬어야 하는 고독한 디버깅의 길을 걷게 된다.(...)
5. 여담
- 이름의 g는 구글이 아니다?: gRPC의 'g'가 당연히 'Google'의 약자일 것이라 생각하는 사람들이 많지만, 실제로는 구글이 릴리스 버전마다 g의 뜻을 매번 다르게 정해 두고 있다. 예를 들어 v1.1에서는 'g'가 'glorious'였고, v1.20에서는 'good', v1.34에서는 'gargantuan'이었다. 구글 나름의 괴짜 같은 이스터 에그 중 하나다.
- IDL의 엄격한 상속:
.proto파일에 필드를 선언할 때, 필드마다 고유한 번호(태그 넘버)를 지정해 주어야 한다. 이 번호는 한 번 정해지면 영구 불변이며, 번호를 바꿨다가는 기존에 서비스 중이던 레거시 클라이언트들이 패킷을 엉망으로 오해해 통신이 완전히 폭발하는 하위 호환성 붕괴를 초래한다. - Stub의 자동 제너레이션:
.proto한 장만 적어두면 구글이 친히 제공하는 컴파일러(protoc)가 C++, Java, Go, Python, Node.js 등 수많은 언어의 클라이언트-서버 보일러플레이트 코드(Stub)를 1초 만에 자동 생성해 주어 대단히 편리하다.(...)