같은 데이터를 Protobuf로 바꿨더니 페이로드가 70% 줄었습니다 (직렬화)

⚡️ 핵심 요약

1. 크기 70% 차이의 원인

JSON은 사람이 읽는 문자열이라 숫자도 문자로 풀어 쓰고 필드 이름·콜론·따옴표·중괄호까지 전부 바이트를 차지하지만, Protobuf는 필드 이름 대신 번호를 쓰고 숫자를 바이너리로 직접 저장하며 구분자도 없어 같은 데이터가 훨씬 작아진다.

2. 바이너리의 대가

Protobuf는 바이너리라 별도 도구 없이 내용을 확인할 수 없어 디버깅이 가장 큰 문제이고, 필드 번호로 데이터를 식별하는 구조 때문에 번호를 삭제 후 재사용하면 이전 버전 클라이언트가 데이터를 잘못 읽는 스키마 관리 부담이 생긴다.

3. 실무의 이분법

어느 한쪽이 우월한 것이 아니라, 성능이 필요한 내부 통신은 Protobuf, 유연성이 필요한 외부 통신은 JSON으로 용도에 따라 나누는 것이 실무의 선택이다.

목차

1. 직렬화 원리: 텍스트 vs 바이너리가 만드는 크기·속도 차이

직렬화는 메모리에 있는 객체를 바이트 배열로 바꾸는 과정이다. 네트워크로 보내거나 파일에 저장하려면 메모리 구조 그대로는 쓸 수 없기 때문이다. 이때 '어떤 바이트로 바꾸느냐'가 두 방식의 본질적 차이다.

구분 JSON Protobuf
표현 방식 사람이 읽는 문자열 바이너리
숫자 저장 문자열로 풀어 씀 (자릿수만큼 바이트) 정수를 바이너리로 직접 저장
필드 식별 필드 이름을 데이터에 포함 필드 번호 사용
구조 오버헤드 콜론·따옴표·중괄호가 바이트 차지 구분자·따옴표 없음
파싱 따옴표 탐색, escape 처리, 숫자 문자열→정수 변환 바이트를 그대로 읽음

크기뿐 아니라 속도 차이도 표현 방식에서 나온다 — JSON은 문자열을 파싱하는 단계(따옴표 찾기, escape 처리, 문자열→정수 변환)를 거쳐야 하지만 Protobuf는 바이트를 그대로 읽으면 끝이다.

⚠️ 화자는 '같은 정보를 담고 있는데 왜 크기가 다른가'라는 질문으로 시작한다. 차이의 본질은 담긴 정보가 아니라 표현 방식 — 사람이 읽을 수 있는 문자열이냐, 기계가 그대로 읽는 바이트냐 — 에 있다.
📝 적용 예시

숫자 123,400원 저장 예시: ① 정수(바이너리)로 저장하면 2바이트로 충분 → ② 같은 값을 JSON 문자열로 저장하면 5바이트 소요 → ③ 여기에 필드 이름·콜론·따옴표·중괄호 오버헤드가 더해짐 → ④ 결과적으로 서비스 간 통신에서 JSON→Protobuf 전환 시 같은 데이터 크기가 70% 감소.

▶️ 관련 스크립트

2. Protobuf의 트레이드오프: 디버깅과 스키마 관리

'전부 Protobuf로 바꾸면 되지 않나'라는 생각이 들지만 그렇게 간단하지 않다. 화자가 꼽는 가장 큰 문제는 디버깅이다 — 바이너리라서 별도 도구 없이는 내용을 확인할 수 없다.

두 번째는 스키마 관리 문제다. Protobuf는 필드 이름이 아니라 필드 번호로 데이터를 식별하기 때문에, 한 번 쓴 번호를 삭제 후 재사용하면 이전 버전 클라이언트가 데이터를 잘못 읽는다. 반면 JSON은 필드 이름이 데이터 자체에 포함되어 있어 이런 버전 호환 문제가 없다. 앞 섹션에서 본 크기·속도 이점(필드 번호 사용, 바이너리 저장)이 곧 이 비용의 원인이라는 점이 핵심이다.

⚠️ 필드 번호 재사용 문제는 버그가 아니라 '이름 대신 번호로 식별한다'는 설계 자체에서 오는 구조적 제약이다 — 크기를 줄여준 바로 그 선택이 스키마 관리 부담을 낳는다.
▶️ 관련 스크립트

3. 마무리 정리: 실무의 용도별 선택

화자의 결론은 하나를 고르는 것이 아니라 용도에 따라 나누는 것이다.

용도 선택 이유
내부 통신 Protobuf 성능(크기·파싱 속도)이 필요
외부 통신 JSON 유연성(가독성, 필드 이름 기반 호환성)이 필요

JSON이 느린 건 사람이 읽을 수 있는 대가라는 것이 화자의 마무리 관점이다 — 느림은 결함이 아니라 가독성과 맞바꾼 비용이므로, 그 대가를 치를 가치가 있는 곳(외부 통신)과 없는 곳(내부 통신)을 구분하는 것이 실무의 답이다.

⚠️ 성능과 유연성은 하나의 프로토콜 안에서 동시에 얻는 것이 아니라 통신 경계(내부 vs 외부)를 기준으로 배치하는 것이다. 두 방식은 우열 관계가 아니라 '무엇을 대가로 무엇을 얻느냐'가 다른 트레이드오프 관계다.
▶️ 관련 스크립트

개발 가이드라인