192. gRPC (Google Remote Procedure Call) 구조

⚠️ 이 문서는 마이크로서비스(MSA) 간의 백엔드 내부 통신에서, 텍스트로 된 무겁고 느린 JSON과 HTTP/1.1 기반의 REST API를 버리고, **데이터를 가벼운 이진(Binary) 코드로 압축하고 양방향 스트리밍(HTTP/2)을 지원하여 내부 서버 간 통신 속도를 극도로 끌어올리는 구글의 오픈소스 고성능 원격 프로시저 호출(RPC) 프레임워크인 'gRPC'**를 다룹니다.

핵심 인사이트 (3줄 요약)

  1. 본질: 다른 서버(컴퓨터)에 있는 함수나 메서드를 마치 내 컴퓨터(로컬)에 있는 함수(user.getProfile())처럼 투명하고 쉽게 불러 쓰게 해주는 원격 호출(RPC) 기술의 현대적 최강자다.
  2. 가치: REST API가 JSON이라는 '사람이 읽기 편한 텍스트'를 보내느라 낭비하던 네트워크 대역폭과 파싱(직렬화/역직렬화) 시간을, '기계만 알아듣는 압축된 0과 1의 바이너리'로 바꿔버려 속도를 10배 이상 가속화한다. MSA 백엔드 내부망 통신의 필수 무기다.
  3. 기술 체계: 통신의 운반체로는 빠르고 끈질긴 HTTP/2를 채택하고, 상자에 담을 데이터의 규격(포맷)으로는 구글이 만든 가볍고 엄격한 **Protocol Buffers (프로토버프, Protobuf)**를 사용하여 두 마리 토끼(속도와 효율)를 다 잡았다.

Ⅰ. REST API와 JSON의 치명적 한계

사용자(프론트엔드)와 소통하기엔 최고지만, 기계끼리 대화하기엔 너무 수다스럽다.

  1. JSON의 비만 문제 (Payload Bloat):
    • A 서버가 B 서버로 {"id": 123, "name": "홍길동"}을 보낸다 치자.
    • 진짜 필요한 정보는 123홍길동인데, 기계는 굳이 필요 없는 id, name, 큰따옴표(""), 중괄호({}) 같은 텍스트 껍데기까지 모두 네트워크로 실어 보내야 한다.
  2. 직렬화(Serialization) 파싱 병목:
    • 텍스트 덩어리로 날아온 JSON을 자바나 파이썬 객체(Object)로 변환(역직렬화)하는 과정은 은근히 CPU를 많이 잡아먹는다. 초당 수십만 번 호출되는 내부망 서버끼리의 통신에서는 이 낭비가 거대한 병목이 된다.
  3. HTTP/1.1의 답답함:
    • 기존 REST는 HTTP/1.1을 써서, 한 번 질문(Request)하면 대답(Response)을 받을 때까지 회선이 꽉 막혀있다(Head-of-Line Blocking). 한 번의 연결로 데이터를 쉴 새 없이 주고받는 양방향 스트리밍 통신이 불가능했다.

📢 섹션 요약 비유: REST API(JSON) 통신은 같은 회사 직원(기계)들끼리 100원짜리 메모를 넘길 때마다, 굳이 비싼 금박 봉투에 담고 "존경하는 수신자 제위께..."라고 장황한 인사말(불필요한 텍스트 헤더)을 꽉꽉 채워 우편으로 주고받는 낭비적인 회사 문화와 같습니다.


Ⅱ. gRPC의 무기 1: Protocol Buffers (프로토버프)

군더더기를 싹 빼고 오직 순수한 뼈대와 알맹이만 남긴다.

  1. IDL (인터페이스 정의 언어)의 계약서:
    • gRPC를 쓰려면 A 서버(Java)와 B 서버(Python)가 통신하기 전에 user.proto라는 설계도(명세서) 파일을 먼저 작성해야 한다.
    • message User { int32 id = 1; string name = 2; } 처럼 "1번 자리는 무조건 32비트 숫자 ID, 2번 자리는 무조건 이름 문자열이야"라고 법으로 강제한다.
  2. 바이너리 압축의 마법:
    • 이제 B 서버로 데이터를 보낼 때 {"id": 123, "name": "홍길동"}이라는 텍스트를 보내지 않는다.
    • 그냥 컴퓨터 이진수로 [1번 자리 123, 2번 자리 홍길동]이라는 빽빽하게 압축된 바이트(Byte) 덩어리만 휙 던진다. 수신자도 user.proto 설계도를 갖고 있으니 "아, 첫 번째 덩어리는 ID구나" 하고 0.001초 만에 조립(역직렬화)해버린다.
  3. 강타입(Strongly Typed)의 안전성:
    • REST API는 상대방이 JSON 필드를 멋대로 바꾸면 런타임 중에 에러가 터진다.
    • Protobuf는 컴파일 시점에 클래스 코드를 자동 생성해 주므로, 개발자가 실수로 숫자 자리에 문자를 넣으려 하면 타이핑할 때 에러 밑줄을 그어주어(Compile Error) 런타임 사고를 원천 봉쇄한다.

📢 섹션 요약 비유: 군대에서 통신병들이 무전할 때 "본부, 현재 1소대가 적군 10명을 발견했습니다"라고 길게 말하지 않고, 암호표(Proto 파일)를 보고 "알파-1-탱고-10" 이라는 짧은 음어(바이너리)만 툭 던져버려 통신 시간과 적의 도청을 완벽히 차단하는 초고속 전문 통신 체계입니다.


Ⅲ. gRPC의 무기 2: HTTP/2와 양방향 스트리밍

전화 한 통 걸어서 끊지 않고 무제한으로 대화를 나눈다.

  1. HTTP/2 멀티플렉싱 (Multiplexing):
    • gRPC의 기저에 깔려 있는 HTTP/2는 하나의 파이프(TCP 연결) 안에 수많은 요청과 응답을 차선 구분 없이 마구잡이로 동시에 쏟아부을 수 있다. 연결을 맺고 끊는 지연 시간(Handshake)이 획기적으로 사라진다.
  2. 4가지 통신 패턴의 지원:
    • Unary: 일반 REST처럼 하나 던지고 하나 받는 방식.
    • Server Streaming: 클라이언트가 요청 하나를 던지면, 서버가 주식 호가처럼 수천 개의 데이터를 끊지 않고 콸콸콸 내려보냄.
    • Client Streaming: 클라이언트가 센서 데이터 수만 개를 쏴주고, 다 끝나면 서버가 "잘 받았어" 하고 하나만 응답함.
    • Bidirectional (양방향) Streaming: 채팅 앱이나 줌(Zoom) 화상 회의처럼 서버와 클라이언트가 연결을 계속 살려둔 채 양쪽에서 미친 듯이 실시간으로 동시에 데이터를 주고받음.
  3. 한계와 실무 적용 (프론트엔드의 벽):
    • gRPC는 인간(브라우저)이 읽을 수 없는 바이너리 포맷이라 디버깅이 까다롭고, 웹 브라우저(JS)에서 직접 HTTP/2를 깊게 제어하기 힘들어 프론트엔드와 백엔드 간 통신에는 여전히 REST API(또는 GraphQL)가 주로 쓰인다.
    • 하지만 사내망 깊숙이 숨어있는 마이크로서비스들(백엔드 $\leftrightarrow$ 백엔드) 간의 초고속 동기식 혈관 망으로는 gRPC가 사실상 만장일치의 표준(De facto)이 되었다.

📢 섹션 요약 비유: 과거의 편지(REST API)는 우체통에 넣고 며칠 뒤 답장을 받아야 했지만, gRPC(HTTP/2 스트리밍)는 아예 상대방 서버와 상시 통화 상태로 '핫라인 무전기'를 켜놓은 것입니다. 내가 말을 하는 도중에도 상대방의 대답이 쉴 새 없이 스피커로 흘러나오는 완벽한 쌍방향 실시간 대화 채널입니다.