Schema

스키마는 데이터 구조를 의미한다. 스키마가 필요한 이유는 producer가 어떤 데이터를 보낼지 cosumer가 어떤 데이터를 받을지 모르기 때문에 producer와 consumer 간의 계약으로 스키마를 사용한다.

image

스키마가 없으면 제어된 방식으로 데이터 구조를 발전시킬 수 없다. 비즈니스가 변하면 데이터 구조도 변경될텐데 발전시킬 구조화된 데이터 구조가 없으면 안된다. 이렇게 비즈니스에 따라서 데이터 구조가 진화하는것을 Schema Evolution(스키마 진화)라고 한다. 비즈니스가 변경되거나 더 많은 애플리케이션이 동일한 데이터를 활용하기를 원함에 따라 기존 데이터 구조가 진화할 필요성 발생한다.

image

Schema Evolution

스키마는 계속해서 진화하기 때문에 호환성 문제가 있다. 스키마의 버전이 올라갈때 과거의 스키마를 이용해서 데이터를 읽을 수 있으면 하위 호환성을 제공한다. 필드가 삭제되거나 기본값이 있는 필드를 추가하는 경우는 새로운 스키마를 통해서 이전 데이터를 읽는 것이 가능하다. 상위 호환이 가능하다는 것은 이전 스키마를 이용해 새로운 데이터를 읽는 것이 가능한 것을 말한다. 새로운 필드가 추가되거나 기본값이 있는 필드가 삭제되면 상위 호환이 가능하다고 한다. 양쪽이 다 가능한 경우를 full compatibility 라고 한다.

image

따라서, 삭제될 가능성이 있는 필드는 default value를 지정하는 것이 좋고, 추가되는 필드에도 default value를 지정하는 것이 좋다. 그리고 필드의 이름은 변경하지 않는 것이 좋다.

Confluent Schema Registry

confluent에서는 스키마 저장소를 제공해준다. 스키마를 중앙 서버에서 버전을 관리하면서 제공하는 저장소이다. Avro 스키마 저장 및 검색을 위한 RESTful 인터페이스 제공한다. Schema Registry는 특별한 _schemas 라는 Kafka internal Topic에 스키마 정보를 저장한다.

Schema Registry와 AVRO 타입을 쓰면 producer가 kafka topic으로 메세지를 실제로 보내기 전에 AVRO 스키마에 대한 local cache를 찾아본다. 없으면 스키마를 Schema Registry에 보내서 ID와 같이 등록한다. 해당 스키마 ID를 데이터에 집어넣은 다음에 데이터를 kafka topic으로 보내준다. consumer는 AVRO ID가 있으니깐 local cache에서 찾아본다. 없으면 ID를 기반으로 스키마 저장소에 요청해서 해당되는 AVRO 스키마를 가져와서 데이터를 파싱한다. 즉, 스키마를 전송하지 않고 ID 만 데이터에 넣어서 전송한다. ID 매핑되어 있는 스키마는 중앙 저장소인 스키마 저장소에 버전 관리 되면서 저장이 되는것이다. 그만큼 좀더 가볍게 데이터를 전송할 수 있는 것이다.

image

그리고 producer와 consumer는 local cache를 사용하기 떄문에 한번 local cache에 등록되면 이 스키마를 매번 등록하고 불러오는 과정을 생략하고 local cache에 있는것을 사용할 수 있다. 버전업이 되면 새로운 ID를 받아서 local cache에있는 스키마도 갱신이 된다.