개요

소켓과 전통 RPC, 그리고 REST를 거쳐 gRPC가 등장한 배경과 핵심 특성 정리 HTTP/2와 Protocol Buffers를 결합한 gRPC의 구조, Proto 파일 작성 규칙, 그리고 실제 인코딩 원리까지 흐름 중심으로 정리 후반부에는 인증과 장애 상황에서의 동작 특성, 도입 적합 영역 요약

등장 배경

  • Server-Client 모델의 확산 배경 초기 모놀리식 메인프레임 시대에는 네트워크 통신 중요도 낮음 소형 컴퓨터와 워크스테이션 보급으로 기능 분산 필요성 증가 네트워크 계층 표준화 진행과 함께 서버 간 통신이 핵심 과제로 부상

  • IPC 관점에서의 소켓과 한계 프로세스는 기본적으로 상호 독립, 필요 시 IPC로 데이터 교환 소켓은 L7에서 L4의 TCP/UDP를 사용하기 위한 창구 역할 API 편의성은 높지만 연결 관리, 재시도, 오류 처리, 데이터 포맷팅 등을 애플리케이션이 직접 부담 서비스 복잡도가 증가할수록 데이터 포맷 관리 난이도 증가

  • RPC의 등장과 스텁 개념 원격 서버의 프로시저를 로컬처럼 호출하는 추상화 제공 IDL 기반 인터페이스 정의로 언어 간 상호 운용성 확보 Client Stub은 파라미터 마샬링과 응답 언마샬링 담당, Server Stub은 역변환과 결과 변환 담당 RPC 구현은 다양하게 시도되었으나, 복잡한 배포와 이기종 환경 한계로 대중적 확산에는 제약 존재

  • REST의 부상과 제약 HTTP/1.1 기반 리소스 중심 아키텍처로 보편화 텍스트 기반, 단순 캐시, 인프라 친화성 강점 그러나 표준 규약 부재로 파라미터와 응답 스키마가 명시적이지 않음 메서드 수의 제약으로 세밀한 행위 모델링에 한계

  • 데이터 포맷의 선택지와 한계 XML은 확장성 높지만冗長성으로 인한 비효율 존재 JSON은 간결하나 타입 표현 한계로 파싱 후 형변환 비용 발생 두 포맷 모두 문자열 기반이라 직렬화 비용과 전송량 증가 요인

gRPC 핵심 개념

  • 정의 gRPC는 구글이 오픈소스로 공개한 고성능 RPC 프레임워크 HTTP/2 위에서 Protocol Buffers 기반 IDL과 직렬화 사용 언어와 플랫폼을 가리지 않는 상호 운용성 확보, 서비스와 메시지 스텁 코드 자동 생성

  • 차별점 요약 HTTP/2의 멀티플렉싱, 헤더 압축, 서버 푸시, 단일 커넥션 활용 Protocol Buffers의 이진 직렬화로 메시지 크기 절감 및 파싱 비용 절감 Proto 파일 공유만으로 양측 계약 정합성 유지 가능

HTTP/2 핵심 포인트

  • 단일 커넥션에서 멀티플렉싱으로 동시 요청 처리, HOL 블로킹 완화
  • HPACK 기반 헤더 압축과 중복 제거로 오버헤드 감소
  • 서버 푸시로 클라이언트 요청 없이도 리소스 선제 제공 가능
  • gRPC는 스트림과 흐름 제어를 활용해 양방향 스트리밍, 흐름 제어, 우선순위 지정에 유리한 통신 모델 구성

Protocol Buffers 개념과 이점

  • 구조화된 데이터의 이진 직렬화 포맷
  • Key-Value 쌍 기반 메시지 표현, 필드 번호와 Wire Type으로 식별
  • JSON 대비 현저히 작은 메시지 크기와 빠른 인코딩/디코딩 성능
  • 명세를 Proto 파일로 관리하므로 스키마 진화 전략 수립 용이

Proto 파일 기본 구성

  • Message와 Field 메시지는 교환 데이터의 구조 정의 단위 각 필드는 타입과 고유한 필드 번호를 가짐 권장 네이밍 가이드

    • message, service, method는 CamelCase 권장
    • field는 snake_case 권장, 숫자로 시작 금지 예) query_1 허용, 1_query 금지
  • Field Number와 Tag 필드 번호 범위 1부터 536870911까지 사용 가능, 1900019999는 예약 영역으로 사용 불가 메시지 크기 최적화를 위해 자주 쓰는 필드는 115 구간 배치 권장 Tag는 Key의 일부로 사용되고 Key는 (field_number « 3) | wire_type 형태로 인코딩됨

  • proto2 vs proto3 proto2는 required, optional, repeated 규칙 사용, 언어 지원 제한적 proto3는 required, optional 제거, repeated만 유지, 언어 지원 폭 넓음 신규 프로젝트는 proto3 권장

  • Field Rule과 packed repeated로 리스트 표현 가능 숫자형 repeated는 [packed = true]로 value만 연속 저장 가능, 크기 절감 효과

Package와 네임스페이스

  • 패키지는 메시지와 서비스의 이름 충돌 방지 목적
  • 동일한 식별자라도 패키지를 통해 명확히 구분 가능
  • 메시지 규모가 커질수록 패키지 명시로 가독성과 충돌 방지 효과 증가

Service와 RPC 메서드 정의

  • Service 블록에서 RPC 메서드 시그니처 정의
  • 기본은 단일 요청·응답의 Unary RPC
  • stream 키워드로 스트리밍 RPC 정의 가능
    • 서버 스트리밍, 클라이언트 스트리밍, 양방향 스트리밍 지원
  • 서비스와 메서드 네이밍 CamelCase 권장

Protocol Buffers 인코딩 원리

  • 메시지 인코딩 모델 메시지는 Key-Value 쌍의 연속으로 직렬화 Key는 필드 번호와 Wire Type을 합성하여 표현

    • Key = (field_number « 3) | wire_type
  • Wire Type 분류 요약

    • 0: Varint 정수형 계열
    • 1: 고정 64비트 수치형 계열
    • 2: 길이 구분 문자열, 바이트, 임베디드 메시지, packed 리스트 등
    • 5: 고정 32비트 수치형 계열
  • Varints와 msb 비트 정수형은 Varints 사용, 바이트당 상위 1비트를 연속 여부 플래그로 사용 1이면 뒤에 바이트가 이어짐, 0이면 종료 의미 하위 그룹 우선 저장 규칙 적용

  • 필드 번호 115 최적화 이유 1바이트 Key에서 wire type 3비트와 msb 규칙을 고려하면 필드 번호 표현에 실질 가용 비트가 제한됨 자주 쓰는 필드를 115로 배치 시 Key 크기 최소화 효과

  • 정수 300 인코딩 예시 300의 이진 표현 100101100 분할 후 7비트 그룹으로 나눔 하위 그룹 우선 규칙에 따라 역순 배치, 각 바이트의 msb 설정 결과 바이트 시퀀스는 0b10101100 0b00000010 형태로 직렬화됨 역변환은 msb 제거, 역순 정렬, 7비트 그룹 결합 순서로 복원

  • 부호 있는 정수 ZigZag 인코딩 음수 표현 효율을 위해 sint 계열 타입에서 ZigZag 매핑 사용 부호 없는 정수 공간으로 매핑하여 Varints 효율 유지

  • 고정 길이 수치형 wire type 1은 64비트 고정 길이, wire type 5는 32비트 고정 길이로 직렬화 비트 패턴을 그대로 기록하므로 간단한 변환

  • 길이 구분 타입 wire type 2 문자열, 바이트, 임베디드 메시지, packed 리스트 등은 길이 prefix + payload 구조 길이도 Varints로 표현되므로 1바이트 이상이 될 수 있음 문자열은 UTF-8로 인코딩

  • 임베디드 메시지 인코딩 메시지를 또 다른 메시지의 필드로 포함 가능 임베디드 메시지는 wire type 2로 표현되고 길이 prefix 뒤에 내부 메시지의 Key-Value 시퀀스가 이어짐

값 타입과 기본값

  • 스칼라 타입 매핑 각 언어별 생성 코드에서 타입 매핑 상이함에 유의

    • 자바는 uint32/uint64를 부호 있는 정수로 취급, 최상위 비트 주의
    • 파이썬은 타입 체킹과 정수 크기 취급이 구현에 따라 상이할 수 있어 주의
    • PHP는 32비트 환경에서 64비트 정수가 문자열로 매핑될 수 있음
  • 기본값 규칙 숫자는 0, 문자열은 빈 문자열, bool은 false, 바이트는 빈 바이트 배열 enum은 첫 번째 상수가 기본값이므로 첫 상수는 0으로 정의 권장 메시지 필드는 unset 상태에서 언어별 기본 동작 차이가 있을 수 있어 각 언어 API 레퍼런스 확인 필요

Enum 사용 규칙과 옵션

  • 기본 문법 정수 상수의 열거형, 이름과 값의 매핑을 생성 첫 번째 상수는 기본값으로 사용되므로 값 0으로 정의 권장

  • allow_alias 옵션 동일 값에 대해 여러 이름 허용 가능 사용 측에서는 oneof 등으로 단일 선택 로직을 명확히 구성 필요

  • reserved 옵션 과거에 사용했던 값이나 이름을 재사용하지 못하도록 예약 가능 스키마 진화 시 호환성 사고 방지에 유용 단, enum 정의의 첫 줄은 하나 이상의 상수 선언이 필요, reserved만 단독 선언 불가

Map 타입 주의사항

  • key는 스칼라 또는 문자열만 허용, value는 map을 제외한 모든 타입 가능
  • map 자체는 repeated와 달리 순서 보장 대상 아님
  • 언어별 구현 차이가 크므로 직렬화 결과 이외의 순서나 동작 가정 금지
  • 중첩 map은 직접 지원하지 않음, map을 보유한 메시지로 분해하여 구성 권장 단, 스텁 구조가 복잡해지고 메시지 크기 증가 가능, 명명 최소화 등으로 비용 절감 필요

gRPC 인증

  • SSL/TLS 기반 채널 보안 서버와 클라이언트 각각 보안 자격 설정 후 암호화 통신 수행 클라이언트는 Dial 시 보안 옵션 설정, 서버는 리스너 생성 시 인증서 적용

  • 토큰 기반 인증 OAuth2 등 토큰을 메타데이터에 실어 전달하는 패턴 지원 API 게이트웨이 또는 인터셉터를 통한 토큰 검증 조합 가능

장애와 페일오버 관찰 노트

  • 테스트 환경 요약 gRPC 라이브러리 1.x 계열, Protocol Buffers 3.x, 언어는 Go로 실험 버전은 이해 보조용 정보 수준, 구현체나 설정에 따라 결과 달라질 수 있음

  • 서버 다운 상태에서의 클라이언트 요청 서버 준비 전 요청은 재시도 발생, 새 세션이 성립할 때까지 전송 시도 반복 구현체 기본 동작에서 재시도 횟수와 백오프는 채널 옵션에 영향 받음

  • 서버 다운 후 복구 케이스 서버 다운 시 클라이언트 측 타임아웃에 도달하면 호출 종료 또는 재시도 전환 타임아웃을 충분히 길게 두면 서버 복구 후 재전송에 응답해 새 세션으로 연결 가능

  • 재전송 상한과 종료 기본 재전송 한계 도달 시 호출은 종료됨 관찰 기준으로 약 8회 수준에서 종료되는 패턴 확인, 구체 값은 구현과 설정에 의존

  • L4 로드밸런서 환경의 페일오버 VIP를 통한 요청 중 연결된 활성 서버가 다운되면 기존 세션은 정상 종료 후 즉시 다른 백엔드로 재연결 시도 L4 모드는 프록시, 분산 정책은 라운드로빈으로 설정한 시나리오 기준 관찰

장점과 특징 요약

  • 생산성과 유지보수성 IDL 한 번 정의로 다언어 서버·클라이언트 스텁 자동 생성 계약 우선 개발로 인터페이스 일관성 확보

  • 다언어·다플랫폼 지원 동일 Proto로 다양한 언어와 런타임에서 동작하는 코드 생성

  • HTTP/2 기반 양방향 스트리밍 서버와 클라이언트가 동시에 데이터를 스트림으로 교환, 실시간 상호작용에 유리

  • 메시지 크기와 성능 최적화 헤더 압축과 이진 직렬화로 전송량과 파싱 비용 절감

  • 생태계와 통합성 인증, 트레이싱, 로드밸런싱, 헬스체크, 게이트웨이 등 다양한 도구와의 결합 용이

  • 제약 인지 포인트 브라우저에서의 직접 호출은 제한적, 일반적으로 게이트웨이나 gRPC-Web을 통해 접근 텍스트가 아닌 바이너리 스트림이라 디버깅 시 도구 지원 필요

언제 gRPC를 쓰면 좋은가

  • 마이크로서비스 아키텍처의 서비스 간 통신 서비스 경계가 명확하고 인터페이스 계약이 중요한 환경에 적합 다언어 팀 구성에서 동일 계약으로 구현 단순화

  • 서버 간 백엔드 통신 브라우저 경유 불필요한 사내 또는 데이터센터 내부 호출 경로에 적합

  • 자원 제한 환경과 비용 최적화 메시지 크기 감소와 효율적 연결 사용으로 CPU, 네트워크, 호출 단가 절감 기대

  • 인프라 자동화와 운영 주요 네트워크 및 인프라 장비, 플랫폼 영역에서 gRPC 기반 원격 제어나 모니터링 지원 확대 추세

참고 메모와 베스트 프랙티스

  • 스키마 진화 전략 필드 삭제 대신 reserved로 보호, 기존 필드 번호 재사용 금지 새 필드는 기본값과 하위 호환 고려해 추가

  • 필드 번호 설계 고빈도 필드에 1~15 배치로 Key 크기 최소화 장기 유지보수 고려해 번호 영역을 목적별로 블록화

  • 오류 처리와 재시도 타임아웃과 재시도 정책을 서비스 특성별로 분리 설정 권장 멱등성 보장 메서드에만 재시도 허용, 백오프와 데드라인 명시

  • 스트리밍 설계 흐름 제어와 백프레셔 고려, 서버·클라이언트 버퍼 관리와 취소 전파 구현 메시지 경계 유지와 적절한 배치 크기 선택

  • 관측성 인터셉터로 메타데이터 로깅, 상태 코드와 지연시간 추적 트레이싱 컨텍스트 전파와 샘플링 비율 관리

마무리

gRPC는 HTTP/2와 Protocol Buffers의 조합으로 높은 성능과 명확한 인터페이스 계약을 제공하는 RPC 프레임워크 분산 시스템에서의 서비스 간 통신, 리소스 최적화, 다언어 팀 협업에 강점 Proto 파일로 계약을 중심에 두고, 인코딩 원리와 스키마 진화 규칙을 이해하면 장기 유지보수 비용을 크게 줄일 수 있음 브라우저 경로, 디버깅 도구, 재시도 정책 등 운영 상 고려사항을 함께 설계할 때 안정적인 도입 가능

참고자료