프로토콜 버퍼 3에서 필수 및 옵션이 제거 된 이유


214

나는 최근에 사용하고 있습니다 gRPCproto3, 나는 것으로 나타났습니다 requiredoptional새로운 구문에서 제거되었습니다.

proto3에서 필수 / 선택 사항이 제거 된 이유를 누구나 설명해 주시겠습니까? 이러한 종류의 제약은 정의를 강력하게 만드는 데 필요한 것 같습니다.

구문 proto2 :

message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
}

구문 proto3 :

syntax = "proto3";
message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

답변:


390

required논쟁은 많은 논쟁과 화염 전쟁의 핵심이었습니다. 큰 캠프가 양쪽에 존재했습니다. 한 캠프는 가치를 보장하는 것을 좋아했고 그 한계를 극복 할 의향이 있었지만 다른 캠프는 required안전하게 추가하거나 제거 할 수 없으므로 위험하거나 도움이되지 않았다고 느꼈습니다 .

required필드를 드물게 사용해야 하는 이유에 대해 더 자세히 설명하겠습니다 . 이미 프로토를 사용하고 있다면 이전 응용 프로그램은 해당 필드를 제공하지 않으며 일반적으로 응용 프로그램은 오류를 잘 처리하지 못하므로 필수 필드를 추가 할 수 없습니다. 이전의 모든 응용 프로그램을 먼저 업그레이드 할 수 있지만 실수를하기 쉬울 수 있으며 임의의 데이터 저장소에 metocache를 저장하는 경우에도 도움이되지 않습니다 . 필수 필드를 제거 할 때 동일한 상황이 적용됩니다.

많은 필수 필드는 "명백하게"요구 될 때까지 ... 메소드에 대한 id필드 가 있다고 가정 해 봅시다 Get. 즉됩니다 분명히 필요합니다. 나중에 나중에 idint에서 string으로, int32에서 int64 로 변경해야 할 수도 있습니다 . 이를 위해서는 새로운 muchBetterId필드를 추가해야합니다. 이제 지정 해야하는 이전 id필드 가 남아 있지만 결국 완전히 무시됩니다.

이 두 가지 문제가 합쳐 required지면 유익한 분야 의 수가 제한되고 캠프는 여전히 가치가 있는지 논쟁합니다. 반대자 required들은 반드시 아이디어에 반대하는 것이 아니라 현재의 형태에 반대했다. 더 나은 실패 모델을 확인하면서 required보다 고급의 것을 확인할 수있는보다 표현적인 검증 라이브러리를 개발할 것을 제안한 사람들 name.length > 10도 있습니다.

Proto3는 전체적으로 단순성을 선호하는 것으로 보이며 required제거가 더 간단합니다. 그러나 required프리미티브에 대한 필드 존재 제거 및 재정의 기본값 제거와 같은 다른 기능과 결합 할 때 proto3에 대한 의미를 제거하는 것이 더 설득력이 있습니다.

나는 프로토 버프 개발자가 아니며 주제에 대해 권위있는 사람은 아니지만 설명이 유용하기를 바랍니다.


23
네. : 또한 필수 필드로 끔찍하게 잘못 될 수있는 사물의 확장 된 설명을 참조하십시오 capnproto.org/...
켄튼 바르다

8
선택 사항은 제거되지 않습니다. proto3에서는 모든 것이 선택 사항입니다. 그러나 예, 필드 가시성 (has_field)이 제거되었습니다. . 프리미티브의 . 필드 가시성이 필요한 경우 와 같은 메시지가있는 wrappers.proto 를 사용하십시오 StringValue. 메시지이므로 has_field를 사용할 수 있습니다. 이것은 많은 언어에서 흔히 사용되는 "권투"입니다.
에릭 앤더슨

9
반대로 proto3에서 "선택적"이 제거 된 것 같습니다. 모든 필드가 존재하며 기본값으로 채워집니다. 기본 필드가 사용자에 의해 채워 졌는지 또는 기본적으로 채워 졌는지 알 수있는 방법이 없습니다. 기본적으로 포인터 인 메시지 필드는 null 값을 가질 수 있다는 점에서 선택 사항입니다.
Vagrant

14
나는 protobuf가 화염 전쟁을 시작하도록 명시 적으로 고안된 언어 인 것 같은 느낌이 든다
랜디 L

5
대부분의 사람들이 자신의 API를 버전 화하고 싶지 않은 것 같습니다. "역방향 호환성"을 위해 모든 것을 선택적으로 만드는 것이 더 쉽습니다.
Holoceo

41

protobuf Github 문제 에서 설명을 찾을 수 있습니다 .

필수 필드는 일반적으로 유해하고 프로토 타입의 호환성 의미를 위반하는 것으로 간주되므로 proto3에서 필수 필드를 삭제했습니다. protobuf를 사용하는 전체 아이디어는 프로토콜 정의에서 필드를 추가 / 제거하면서 최신 바이너리 및 이전 바이너리와 완전히 호환 가능하다는 것입니다. 필수 필드는 이것을 깨뜨립니다. 필수 필드를 .proto 정의에 안전하게 추가 할 수 없으며, 기존의 필수 필드를 안전하게 제거 할 수 없습니다.이 두 가지 조치로 인해 와이어 호환성이 손상되기 때문입니다. 예를 들어, 필수 필드를 .proto 정의에 추가하면 새 정의로 작성된 바이너리는 필수 필드가 이전 데이터에 없기 때문에 이전 정의를 사용하여 직렬화 된 데이터를 구문 분석 할 수 없습니다. 복잡한 시스템에서. 프로토 타입 정의는 시스템의 여러 구성 요소에서 광범위하게 공유되므로 필수 필드를 추가 / 제거하면 시스템의 여러 부분이 쉽게 중단 될 수 있습니다. 이로 인해 생산 문제가 여러 번 발생했으며 Google은 모든 사용자가 필수 입력란을 추가 / 삭제할 수 없도록 금지하고 있습니다. 이러한 이유로 우리는 proto3에서 필수 필드를 완전히 제거했습니다.

"필수"를 제거한 후 "선택적"은 중복이므로 "선택적"도 제거했습니다.


6
나는 그것을 얻지 못한다. 직렬화 해제 후와 직렬화 해제시 메시지를 삭제하는 것의 차이점은 무엇입니까? 필요한 필드 (예 : id)를 포함하지 않기 때문에 이전 클라이언트에 의해 삭제됩니다.
Shmuel H.

6
@ShmuelH에 동의하는 경향이 있습니다. 필수 필드는 API의 일부가 될 것입니다. 그것은 두 당사자에게 주어진 구문을 통해 자동으로 지원되거나 백엔드에 숨겨져 있습니다. 뿐만 아니라 API를 정의에는 표시 할 수 있습니다
Cruncher의

7
나는 @ShmuelH에 전적으로 동의합니다. 필드는 API에서 어떤 방식 으로든 필요하며 고객이이를 알고있는 데 유용합니다. 이것은 우리가 아직 버전을 얻지 못했다고 생각합니다.
patrickbarker

6
@ShmuelH에 대한 다른 투표. 당신은 이전 버전과 호환되지 않는 방법 (필수 필드를 추가)에 API를 변경할 경우, 반드시 당신이 원하는 당신의 파서가 그것을 감지? 당신의 API를 버전! 원하는 경우 Protobuf에서 완전히 수행 할 수도 있습니다 oneof { MessageV1, MessageV2, etc. }.
Timmmm

1
처음에는 필수 필드가있는 것을 정당화 할 수 없었습니다. 필수 필드를 추가하는 것은 호환되지 않는 변경 사항이며 일반적으로 프로토콜 버전 변경 (예 : 새 메시지 유형)으로 처리해야합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.