애플리케이션과 데이터 요구사항이 변경되면 Kafka 메시지의 구조도 이에 맞게 조정해야 합니다. 효과적인 스키마 수명 주기 관리는 이러한 변경사항을 원활하게 처리하고 데이터 무결성을 유지하는 데 매우 중요합니다. 이 프로세스에는 스키마 변경뿐만 아니라 스키마에 종속된 애플리케이션에 안전하거나 충분히 호환되는 변경사항의 종류를 체계적으로 제어하는 작업도 포함됩니다.
Apache Kafka용 관리형 서비스 스키마 레지스트리는 스키마 관리의 전체 수명 주기를 지원하며 다음 기능을 포함합니다.
새 스키마 버전이 도입될 때 스키마 발전을 관리하기 위해 호환성 규칙 (호환성 유형)을 정의하고 적용합니다. 이러한 규칙은 생산자와 소비자가 계속 올바르게 작동하도록 보장합니다.
운영 제어 (스키마 모드)를 구성하여 다양한 수준에서 스키마의 변경 가능성을 관리하고 데이터 처리 파이프라인을 보호하세요.
스키마 참조를 관리하여 스키마 전반에서 재사용성과 일관성을 높입니다.
스키마 변경 작동 방식
스키마 정의를 수정합니다. 예를 들어
.proto또는.avsc파일에 선택사항 필드를 추가합니다.auto.register.schemas=true로 구성된 프로듀서가 새 스키마를 사용하여 메시지를 전송하거나 API 또는 클라이언트 라이브러리를 사용하여 새 스키마를 명시적으로 등록하려고 시도합니다.새 버전의 등록 요청이 스키마 레지스트리에 도달하면 대상 주제에 대해 구성된 호환성 규칙을 가져옵니다. 이 규칙에 따라 제안된 새 스키마를 필수 이전 버전과 비교합니다.
스키마 버전이 호환되면 새 스키마가 주제 아래 다음 버전으로 등록되고, 새 버전 번호가 할당되며, 정의가 고유한 경우 새
schema_id가 할당될 수 있습니다.제작자 (해당하는 경우)는 메시지에 포함할
schema_id를 수신합니다.스키마 버전이 호환되지 않으면 등록 시도가 실패하고 오류가 반환됩니다.
호환성 유형 정보
스키마 호환성을 사용하면 스키마 레지스트리에서 서로 다른 스키마 버전 간의 호환성 검사를 처리하는 방법을 정의할 수 있습니다. 다음 리소스 패턴 옵션에 표시된 대로 스키마 레지스트리 계층 구조 내의 다양한 수준에서 이러한 구성을 적용할 수 있습니다.
레지스트리 수준: 전체 스키마 레지스트리의 기본 구성을 설정합니다.
- 경로:
projects/project/locations/location/schemaRegistries/schema_registry/config
- 경로:
기본 컨텍스트 내의 주제 수준: 레지스트리의 기본 컨텍스트 내에서 주제의 특정 구성을 설정합니다.
- 경로:
projects/project/locations/location/schemaRegistries/schema_registry/config/subject
- 경로:
특정 컨텍스트 내의 주체 수준: 이름이 지정된 컨텍스트 내의 주체에 대한 특정 구성을 설정합니다.
- 경로:
projects/project/locations/location/schemaRegistries/schema_registry/contexts/context/config/subject
- 경로:
주체 수준에서 설정된 구성은 레지스트리 수준에서 설정된 구성을 재정의합니다.
설정이 주제 수준에서 지정되지 않은 경우 레지스트리 수준에서 값을 상속합니다. 레지스트리 수준에서 명시적으로 설정하지 않으면 기본값은 Backward입니다.
다음과 같은 사용 가능한 유형에 따라 스키마 레지스트리에서 새 스키마 버전을 이전 버전과 비교하는 방식이 결정됩니다.
None: 호환성 검사가 실행되지 않습니다. 모든 변경사항을 허용하지만 클라이언트가 중단될 위험이 높습니다.Backward(기본값): 새 스키마를 사용하는 소비자 애플리케이션은 이전에 등록된 스키마만으로 생성된 데이터를 디코딩할 수 있습니다. 이를 통해 선택적 필드를 추가하고 필드를 삭제할 수 있습니다. 소비자는 생산자보다 먼저 업그레이드해야 합니다.Backward_transitive: 새 스키마를 사용하는 소비자 애플리케이션은 해당 주제의 모든 이전 스키마 버전으로 생성된 데이터를 디코딩할 수 있습니다. 이 설정은Backward보다 엄격합니다.Forward: 새 스키마를 사용하여 생성된 데이터는 이전에 등록된 스키마를 사용하는 클라이언트가 읽을 수 있어야 합니다. 생산자를 먼저 업그레이드해야 하지만 새 스키마를 사용하는 소비자는 훨씬 이전 스키마로 생성된 데이터를 읽지 못할 수 있습니다. 이 설정을 사용하면 선택적 필드를 삭제하고 필드를 추가할 수 있습니다.Forward_transitive: 새 스키마를 사용하여 생성된 데이터는 모든 이전 스키마 버전을 사용하여 읽을 수 있어야 합니다. 이 설정은Forward보다 엄격합니다.Full: 새 스키마는 이전에 등록된 스키마 버전과 하위 호환 및 상위 호환됩니다. 클라이언트는 새 스키마를 사용하여 프로듀서와 관련된 순서로 업그레이드할 수 있습니다. 선택적 필드를 추가하거나 삭제할 수 있습니다.Full_transitive: 새 스키마는 해당 주제의 모든 이전 스키마 버전과 하위 호환 및 상위 호환됩니다. 이 설정은Full보다 엄격합니다.
호환성 유형의 예
Backward 호환성 유형이 있는 스키마 레지스트리가 있다고 가정해 보겠습니다. 또한 이 레지스트리 내에 여러 주제를 만들고 레지스트리의 Backward 호환성을 상속합니다.
user-events라는 특정 주제의 경우 더 엄격한 호환성 규칙이 필요합니다. user-events 주제의 스키마 호환성 수준을 Full로 업데이트합니다.
이 경우 다음 규칙이 적용됩니다.
user-events주제에 등록된 새 스키마 버전은 해당 주제에 대해 이전에 등록된 스키마 버전과 하위 호환 및 상위 호환되어야 합니다.스키마 레지스트리의 다른 주제는 호환성이 명시적으로 구성되지 않은 한 레지스트리 수준
Backward호환성 설정을 따릅니다.
나중에 스키마 레지스트리의 호환성 수준을 Forward로 변경하면 이 변경사항이 레지스트리 내에서 생성된 모든 새 주제의 기본 호환성에 영향을 미칩니다. 하지만 user-events 주제는 명시적으로 설정된 Full 호환성을 유지합니다. 주제 수준 구성이 레지스트리 수준 구성을 재정의하기 때문입니다.
이를 통해 애플리케이션 요구사항에 따라 개별 주제에 대한 특정 호환성 요구사항을 정의할 수 있는 유연성을 유지하면서 전체 레지스트리의 기본 호환성 수준을 설정하는 방법을 알 수 있습니다.
자세한 내용은 호환성 유형 업데이트를 참고하세요.
호환성 모드 권장사항
스키마 변경으로 클라이언트가 중단될 위험이 있으므로
None를 호환성 유형 전략으로 사용하지 마세요.생산자를 먼저 업데이트하려면
Forward또는Forward-transitive과 같은 포워드 기반 전략을 선택합니다. 소비자를 먼저 업데이트하려면Backward또는Backward-transitive과 같은 이전 버전 기반 전략을 선택합니다.여러 이전 스키마 버전과의 호환성을 유지하려면 트랜지티브 전략을 선택하세요. 스키마 버전을 업데이트할 때 호환성을 극대화하고 클라이언트가 중단될 위험을 최소화하려면
Full-transitive전략을 사용하세요.
스키마 참조 정보
스키마 참조를 사용하면 공통 구조를 한 번 정의하고 여러 스키마에서 참조할 수 있습니다. 예를 들어 Address 스키마는 Customer 및 Supplier 스키마의 일부로 사용될 수 있습니다.
이 접근 방식을 사용하면 스키마 전반에서 재사용성과 일관성을 높일 수 있습니다. 또한 스키마 참조를 사용하면 다른 스키마에 의존하는 스키마를 명시적으로 추적하여 명확한 종속 항목을 만들 수 있습니다. 이렇게 하면 스키마 아키텍처의 유지관리성이 개선됩니다.
한 스키마가 다른 공통 스키마를 사용해야 하는 경우 해당 공통 스키마에 대한 참조를 포함합니다. 이 관계는 SchemaReference 구조로 공식적으로 정의됩니다.
SchemaReference에는 다음과 같은 구성요소가 있습니다.
name(문자열): Avro 형식에 대해 참조되는 스키마의 정규화된 이름 또는 스키마 정의 자체 내에서 사용되는 Protobuf 형식에 대해 가져온 유형의 파일 이름입니다.subject(문자열): 참조된 스키마가 스키마 레지스트리에 등록된 주제의 이름입니다.version(int32): 참조된 스키마의 특정 버전 번호입니다.
다른 스키마를 사용하는 스키마는 references 필드에서 이러한 종속 항목을 선언합니다. 이 필드에는 SchemaReference 객체 목록이 포함됩니다.
스키마 참조 예시
Customer 데이터와 Supplier 데이터의 스키마를 정의해야 하고 둘 다 주소를 포함해야 한다고 가정해 보겠습니다. 스키마 참조를 사용하면 주소 구조를 한 번 정의하고 재사용할 수 있습니다.
이 예시를 따르려면 주체 만들기를 참고하세요.
address_schema라는 주제를 만들고 표준 주소의 정의를 등록합니다. 주제를 처음 만들면 해당 주제의 스키마 버전 1도 생성됩니다.Avro
이를 주제
address_schema_avro버전 1로 만들어 저장합니다.{ "type": "record", "name": "Address", "namespace": "com.example.common", "fields": [ {"name": "street", "type": "string"}, {"name": "city", "type": "string"}, {"name": "zipCode", "type": "string"}, {"name": "country", "type": "string", "default": "USA"} ] }Protobuf
이를 주제
address_schema_proto버전 1로 만들어 저장합니다.syntax = "proto3"; package com.example.common; message Address { string street = 1; string city = 2; string zip_code = 3; string country = 4; }customer_schema스키마를 만듭니다. 주소 필드를 반복하는 대신address_schema스키마를 참조합니다.Avro
billingAddress필드의 유형com.example.common.Address은 이전 단계에서 정의한Address스키마를 참조합니다.{ "type": "record", "name": "Customer", "namespace": "com.example.crm", "fields": [ {"name": "customerId", "type": "long"}, {"name": "customerName", "type": "string"}, // This field's type refers to the Address schema {"name": "billingAddress", "type": "com.example.common.Address"} ] }customer_schema_avro를 등록할 때 메타데이터에는 스키마 참조가 포함됩니다.// Conceptual metadata for customer_schema_avro "references": [ { "name": "com.example.common.Address", "subject": "address_schema_avro", "version": 1 } ]Protobuf
customer.proto파일은address.proto를 가져오고billing_address필드에com.example.common.Address를 사용합니다.syntax = "proto3"; package com.example.crm; import "address.proto"; message Customer { int64 customer_id = 1; string customer_name = 2; // This field's type refers to the imported Address message com.example.common.Address billing_address = 3; }customer_schema_proto를 등록할 때 메타데이터에는 스키마 참조가 포함됩니다.// Conceptual metadata for customer_schema_proto "references": [ { "name": "address.proto", "subject": "address_schema_proto", "version": 1 } ]마찬가지로
Supplier스키마의 경우 동일한 공통Address스키마를 가리키는 스키마 참조를 추가합니다.
스키마 모드 정보
스키마 모드는 스키마 레지스트리 또는 특정 주제의 운영 상태를 정의하고 허용되는 수정 유형을 제어합니다. 스키마 모드는 레지스트리 또는 스키마 레지스트리 내의 특정 주제에 적용할 수 있습니다. 다음은 스키마 모드 리소스의 경로입니다.
레지스트리 수준 모드: 전체 스키마 레지스트리에 적용됩니다.
- 경로:
projects/project/locations/location/schemaRegistry/schema_registry/mode
- 경로:
레지스트리 수준 주제 모드: 전체 스키마 레지스트리 내의 특정 주제에 적용됩니다.
- 경로:
projects/project/locations/location/schemaRegistries/schema_registry/mode/subject
- 경로:
다음 모드가 지원됩니다.
Readonly: 이 모드에서는 스키마 레지스트리 또는 지정된 주제를 업데이트할 수 없습니다. 구성을 업데이트하거나 새 스키마 버전을 추가하는 등의 수정이 방지됩니다.Readwrite: 이 모드에서는 스키마 레지스트리 또는 지정된 주제에 대한 쓰기 작업이 제한됩니다. 구성을 업데이트하고 새 스키마 버전을 추가하는 등의 수정이 가능합니다. 이는 새 스키마 레지스트리와 새 주제 모두의 기본 모드입니다.
특정 주제에 대한 수정이 허용되는지 여부를 결정할 때 주제 수준에서 설정된 모드가 스키마 레지스트리 수준에서 설정된 모드보다 우선합니다.
예를 들어 스키마 레지스트리가 Readonly 모드이지만 그 안의 특정 주제가 Readwrite 모드인 경우 해당 특정 주제의 수정이 허용됩니다. 하지만 새 주제의 생성은 레지스트리 수준 Readonly 모드에 의해 제한됩니다.
스키마 모드 예시
모드가 Readwrite로 설정된 스키마 레지스트리를 고려해 보세요. 이 구성을 사용하면 레지스트리에 새 주제를 추가하고 기존 주제에 새 스키마 버전을 추가할 수 있습니다.
실수로 인한 변경으로부터 보호하려는 production-config라는 주제가 있다고 가정해 보겠습니다. production-config 주제의 모드를 Readonly로 설정합니다. 따라서 production-config 주제에는 다음 조건이 적용됩니다.
주제에 새 스키마 버전을 추가할 수 없습니다.
주제의 구성 (예: 호환성 유형)을 업데이트할 수 없습니다.
모드가 명시적으로 설정되지 않은 레지스트리의 다른 주제는
Readwrite모드로 유지되므로 계속 수정할 수 있습니다.레지스트리 자체는 여전히
Readwrite모드이므로 레지스트리에서 주제를 계속 만들 수 있습니다.
나중에 레지스트리 수준 모드를 Readonly로 설정하여 전체 스키마 레지스트리를 유지관리 상태로 전환할 수 있습니다. 하지만 지속적인 테스트를 위해 수정 가능한 상태로 유지해야 하는 다른 주제인 staging-config이 있습니다. Readwrite에 따라 staging-config 주제의 모드를 명시적으로 설정합니다. 따라서 staging-config 주체에는 다음 조건이 적용됩니다.
스키마 레지스트리가 이제
Readonly입니다. 새 주제를 만들 수 없습니다.특정 모드 재정의가 없는 항목과 같은 대부분의 기존 항목도 상속에 의해
Readonly가 됩니다. 새 스키마 버전을 추가하거나 구성을 업데이트할 수 없습니다.production-config주제는 명시적으로 설정된 대로Readonly로 유지됩니다.staging-config주제는 주제 수준 설정이 레지스트리 수준Readonly모드를 재정의하므로Readwrite모드로 유지됩니다.staging-config의 스키마 버전을 계속 추가하고 구성을 업데이트할 수 있습니다.
이 계층 구조 접근 방식을 사용하면 다양한 세분성 수준에서 스키마 수정사항을 유연하게 관리할 수 있습니다.
스키마 모드를 업데이트하는 방법에 대한 자세한 내용은 스키마 모드 업데이트를 참고하세요.
프로덕션에서 스키마 레지스트리를 사용하기 위한 권장 구성
프로덕션 환경에서 스키마를 보호하려면 다음 구성을 적용하세요.
전체 스키마 레지스트리 또는 특정 프로덕션 주제에 대해
mode=READONLY를 설정하여 새 스키마의 등록을 방지합니다.Kafka 클라이언트에
create version권한이 없는지 확인하여 새 스키마 버전을 만들지 못하도록 합니다.Kafka 클라이언트 직렬화기에서
auto.register.schemas=false를 설정합니다. Kafka Connect의 경우 필요에 따라 키 및 값 직렬화 프로그램에 대해 이 설정을 구성합니다.key.serializer.auto.register.schemas=falsevalue.serializer.auto.register.schemas=false
(선택사항) 클라이언트가 주제의 최신 스키마를 사용하도록 강제하려면 직렬화기 또는 역직렬화기에서
use.latest.version=true를 설정합니다. 이 설정은 클라이언트가 특정 메시지와 일치하는 버전이 아닌 주제에 등록된 최신 스키마 버전을 사용하도록 지시합니다.