Protobuf

김도비·2026년 4월 12일

Kafka

목록 보기
7/7

CDC-Pipeline 공부하려다가 자주 등장하는 Protobuf에 대해서 어느정도는 알고 넘어가야 싶어서 정리해본다.


"서비스 간에 데이터를 주고받을 때 어떤 형식을 써야 하지?"

JSON이 익숙하고 편하지만,
대규모 파이프라인에서는 직렬화 형식 하나가 처리 속도, 저장 비용, 스키마 관리 전반에 영향을 미칩니다.
Protocol Buffers(Protobuf)를 개념부터 실제 .proto 문법, 그리고 JSON·Avro와의 비교까지 정리한다.


1. 직렬화(Serialization)란?

프로그램 내부의 객체(Object)를 네트워크 전송이나 파일 저장이 가능한 바이트(byte) 스트림으로 변환하는 과정.
반대 과정은 역직렬화(Deserialization)라고 한다.

[ Python Object ]  →  직렬화  →  [ bytes / string ]  →  역직렬화  →  [ Java Object ]

우리가 매일 쓰는 JSON도 직렬화 포맷의 하나이고, 다만 텍스트 기반이라 사람이 읽기 쉬운 대신, 용량이 크고 파싱 비용이 높다.


2. Protocol Buffers(Protobuf)란?

Protocol Buffers는 Google이 내부 서비스 통신을 위해 개발하고 2008년 오픈소스로 공개한 이진(binary) 직렬화 포맷.

핵심 특징을 세 가지로 요약하면:

특징설명
스키마 우선(Schema-first).proto 파일에 데이터 구조를 먼저 정의
이진 인코딩텍스트가 아닌 바이트로 저장 → 용량 ↓, 속도 ↑
언어 중립하나의 .proto로 Python, Java, Go 등 다양한 언어 코드를 자동 생성

💡 Kafka, gRPC, Flink 등 대부분의 현대 데이터 인프라에서 Protobuf를 기본 또는 권장 포맷으로 지원.


3. .proto 파일 문법 기초

Protobuf를 쓰려면 먼저 스키마 파일(.proto)을 작성해야 함.

3-1. 기본 구조

syntax = "proto3";

package com.example;

message User {
  int32  id    = 1;
  string name  = 2;
  string email = 3;
}
요소설명
syntax = "proto3"사용할 Protobuf 버전 선언 (현재 표준은 proto3)
message하나의 데이터 구조 단위 (JSON의 Object와 유사)
int32, string필드 타입
= 1, = 2필드 번호 — 이진 인코딩의 핵심 (이름 대신 번호로 식별)

3-2. 필드 번호(Field Number)가 중요한 이유

JSON은 키 이름("name", "email")을 바이트 그대로 전송.
Protobuf는 필드 번호(1, 2, 3…)만 전송하므로 페이로드가 훨씬 작아짐.

JSON  →  {"name":"Alice","email":"alice@example.com"}  →  45 bytes
Protobuf  →  [0x0a, 0x05, 0x41, 0x6c, ...]             →  ~18 bytes

⚠️ 필드 번호는 한번 정하면 변경 금지! 번호를 바꾸면 기존 데이터를 역직렬화 불가.

3-3. 자주 쓰는 타입 & 반복 필드

syntax = "proto3";

message Order {
  int64           order_id    = 1;
  string          user_name   = 2;
  repeated string items       = 3;   // 배열(List)
  OrderStatus     status      = 4;   // Enum
  double          total_price = 5;
}

enum OrderStatus {
  PENDING   = 0;
  CONFIRMED = 1;
  SHIPPED   = 2;
}
  • repeated : 배열/리스트를 표현
  • enum : 열거형 상수 정의

4. JSON · Avro · Protobuf 비교

4-1. 특성 비교표

항목JSONAvroProtobuf
인코딩 방식텍스트이진이진
스키마 필요 여부불필요필요 (JSON Schema)필요 (.proto)
가독성✅ 사람이 읽기 쉬움❌ 바이너리❌ 바이너리
직렬화 속도느림빠름가장 빠름
데이터 크기작음가장 작음
스키마 진화(Evolution)자유롭지만 위험제한적이지만 안전필드 번호 기반으로 안전
주요 사용처REST API, 설정 파일Kafka(Confluent), HadoopKafka, gRPC, Flink

4-2. 크기 & 속도 벤치마크 (참고용)

동일한 데이터를 세 포맷으로 직렬화했을 때의 일반적인 비교 결과.

직렬화 크기 (낮을수록 좋음)
────────────────────────────────────────
JSON      ████████████████████  100% (기준)
Avro      ████████████          ~60%
Protobuf  ██████                ~30%

직렬화 속도 (높을수록 좋음)
────────────────────────────────────────
JSON      ██████                1x
Avro      ████████████          ~2x
Protobuf  ████████████████████  ~3-5x

📌 실제 수치는 데이터 구조·환경에 따라 달라지니 참고.

4-3. 언제 어떤 걸 써야 할까?

┌─────────────────────────────────────────────────────┐
│  사람이 직접 읽고 써야 하는 경우                           │
│  → JSON (REST API, 설정 파일, 디버깅)                   │
├─────────────────────────────────────────────────────┤
│  Kafka + Schema Registry, Hadoop/Hive 생태계          │
│  → Avro (Confluent 표준, 동적 스키마 로딩에 유리)          │
├─────────────────────────────────────────────────────┤
│  고성능 스트리밍, gRPC, 서비스 간 통신                     │
│  → Protobuf (속도·크기 최우선, 강타입 보장)                │
└─────────────────────────────────────────────────────┘

5. 데이터 엔지니어링 관점에서의 Protobuf

Kafka와의 연동

Kafka 메시지의 Value를 Protobuf로 직렬화하면 두 가지 이점이 있다.

  1. 네트워크 트래픽 절감 — 메시지가 작아질수록 파티션당 처리량이 올라감
  2. 스키마 버전 관리 — 필드를 추가해도 기존 컨슈머가 정상 동작 (하위 호환)

스키마 진화(Schema Evolution) — 실무에서 중요한 규칙

허용금지
새 필드 추가 (새 번호 사용)기존 필드 번호 변경
optional 필드 삭제기존 필드 타입 변경
필드 이름 변경 (번호는 유지)삭제된 필드 번호 재사용

정리

Protobuf는 처음엔 .proto 파일을 따로 관리해야 하는 번거로움이 있지만, 규모가 커질수록 그 장점이 커짐.

  • 크기와 속도 — 대규모 파이프라인에서 직접적인 비용 절감
  • 스키마 강제 — 엉뚱한 데이터가 파이프라인에 들어오는 것을 컴파일 타임에 차단
  • 언어 중립 — Producer는 Go, Consumer는 Python이어도 스키마 하나로 통일

참고 자료

profile
모든 걸 기록하자

0개의 댓글