카프카에게 메시지는 바이트 배열이다. 내용을 이해하기 쉽도록 부여하는 일정한 구조가 스키마고, 이것은 카프카 밖에 있다.
쓰는 작업과 읽는 작업의 분리
메시지를 쓰는 작업과 읽는 작업을 분리하기 위해서다.
둘이 결합되어 있으면 형식이 바뀔 때마다 구버전과 신버전을 동시에 지원하도록 양쪽을 고쳐야 한다. 잘 정의된 스키마를 공유 저장소에 두면 카프카는 두 버전을 지원하는 작업 없이 메시지를 처리한다.
직렬화에서 자바 객체를 저장할 때 하던 고민과 같은 문제인데, 언어에 매이지 않아야 한다는 조건이 하나 더 붙는다.
Avro
바이너리 직렬화 형식 중 가장 많이 쓴다. 조밀한 형식이라 압축률이 높아 네트워크 대역폭을 아끼고, 메시지 본체와 스키마가 분리되어 저장되므로 코드 생성이 필요 없다. 스키마 변경에 대한 상위 호환성과 하위 호환성을 지원한다.
{
"type": "record",
"name": "User",
"fields": [
{ "name": "id", "type": "long" },
{ "name": "age", "type": ["null", "int"], "default": null }
]
}바이너리라 사람이 읽기 어렵고, 스키마 정의가 복잡해질 수 있으며, 디버깅에 별도 도구가 필요하다.
Protobuf
구글이 만든 언어 중립 직렬화다. 타입 시스템이 강하고 코드 생성을 지원하며 gRPC와 자연스럽게 붙는다. 메시지 크기는 Avro보다도 작다.
message User {
int64 id = 1;
string name = 2;
}대신 스키마 진화 규칙이 엄격하다. 필드 번호가 바이너리 인코딩의 핵심이라 한 번 할당한 번호는 절대 바꿀 수 없고, 바꾸면 기존 데이터를 완전히 다르게 해석한다. JSON에 비하면 가독성도 떨어진다.
JSON
사람이 읽기 쉽고 웹 개발자에게 친숙하며 디버깅이 쉽다. 대신 메시지 크기가 크고 바이너리 형식보다 성능이 떨어지며 스키마 진화 지원이 제한적이다.