목적
protobuf 에서
reserved, 필드 삭제를 했을 때의 변화를 관찰하고,
왜 필드 삭제가 아닌 reserved를 해야 하는지를 알아본다.
상황별 비교
기본 | reserved | delete | |
proto | message TestRequest { int32 m1 = 1; string m2 = 2; int64 m3 = 3; int32 m4 = 4; string m5 = 5; int32 m6 = 6; string m7 = 7; int64 m8 = 8; int32 m9 = 9; string m10 = 10; } |
message TestRequest { int32 m1 = 1; string m2 = 2; int64 m3 = 3; reserved 4; string m5 = 5; int32 m6 = 6; reserved 7; int64 m8 = 8; int32 m9 = 9; string m10 = 10; } |
message TestRequest { int32 m1 = 1; string m2 = 2; int64 m3 = 3; string m5 = 5; int32 m6 = 6; int64 m8 = 7; int32 m9 = 8; string m10 = 9; } |
generated code | boolean done = false; while (!done) { int tag = input.readTag(); switch (tag) { case 0: done = true; break; case 8: { m1_ = input.readInt32(); break; } case 18: { java.lang.String s = input.readStringRequireUtf8(); m2_ = s; break; } case 24: { m3_ = input.readInt64(); break; } case 32: { m4_ = input.readInt32(); break; } case 42: { java.lang.String s = input.readStringRequireUtf8(); m5_ = s; break; } case 48: { m6_ = input.readInt32(); break; } case 58: { java.lang.String s = input.readStringRequireUtf8(); m7_ = s; break; } case 64: { m8_ = input.readInt64(); break; } case 72: { m9_ = input.readInt32(); break; } case 82: { java.lang.String s = input.readStringRequireUtf8(); m10_ = s; break; } default: { if (!parseUnknownField( input, unknownFields, extensionRegistry, tag)) { done = true; } break; } } } |
boolean done = false; while (!done) { int tag = input.readTag(); switch (tag) { case 0: done = true; break; case 8: { m1_ = input.readInt32(); break; } case 18: { java.lang.String s = input.readStringRequireUtf8(); m2_ = s; break; } case 24: { m3_ = input.readInt64(); break; } case 42: { java.lang.String s = input.readStringRequireUtf8(); m5_ = s; break; } case 48: { m6_ = input.readInt32(); break; } case 64: { m8_ = input.readInt64(); break; } case 72: { m9_ = input.readInt32(); break; } case 82: { java.lang.String s = input.readStringRequireUtf8(); m10_ = s; break; } default: { if (!parseUnknownField( input, unknownFields, extensionRegistry, tag)) { done = true; } break; } } |
boolean done = false; while (!done) { int tag = input.readTag(); switch (tag) { case 0: done = true; break; case 8: { m1_ = input.readInt32(); break; } case 18: { java.lang.String s = input.readStringRequireUtf8(); m2_ = s; break; } case 24: { m3_ = input.readInt64(); break; } case 42: { java.lang.String s = input.readStringRequireUtf8(); m5_ = s; break; } case 48: { m6_ = input.readInt32(); break; } case 64: { m8_ = input.readInt64(); break; } case 72: { m9_ = input.readInt32(); break; } case 82: { java.lang.String s = input.readStringRequireUtf8(); m10_ = s; break; } default: { if (!parseUnknownField( input, unknownFields, extensionRegistry, tag)) { done = true; } break; } } |
serialized data
입력
m1 = 43690
m2 = "abcdefg"
m3 = 1431655765
m4 = 43690
m5 = "hijklmn"
m6 = 43690
m7 = "hijklmn"
m8 = 1431655765
m9 = 43690
m10 = "opqrstu"
출력
기본 | reserved | delete |
08 AAD502 12 07 61626364656667 18 D5AAD5AA05 20 AAD502 2A 07 68696A6B6C6D6E 30 AAD502 3A 07 68696A6B6C6D6E 40 D5AAD5AA05 48 AAD502 52 07 6F707172737475 |
08 AAD502 12 07 61626364656667 18 D5AAD5AA05 2A 07 68696A6B6C6D6E 30 AAD502 40 D5AAD5AA05 48 AAD502 52 07 6F707172737475 |
08 AAD502 12 07 61626364656667 18 D5AAD5AA05 2A 07 68696A6B6C6D6E 30 AAD502 40 D5AAD5AA05 48 AAD502 52 07 6F707172737475 |
결론
- 이미 stub이 배포 된 .proto 에서 필드를 제거 할 땐, reserved를 이용하자.
- 절대로 property number는 변경하지 말자.
추가
optional일 때는?
default | optional |
message TestRequest { int32 m1 = 1; int32 m2 = 2; int32 m3 = 3; } |
message OptionalTest { int32 m1 = 1; optional int32 m2 = 2; int32 m3 = 3; } |
boolean done = false; while (!done) { int tag = input.readTag(); switch (tag) { case 0: done = true; break; case 8: { m1_ = input.readInt32(); break; } case 16: { m2_ = input.readInt32(); break; } case 24: { m3_ = input.readInt32(); break; } default: { if (!parseUnknownField( input, unknownFields, extensionRegistry, tag)) { done = true; } break; } } } |
boolean done = false; while (!done) { int tag = input.readTag(); switch (tag) { case 0: done = true; break; case 8: { m1_ = input.readInt32(); break; } case 16: { bitField0_ |= 0x00000001; m2_ = input.readInt32(); break; } case 24: { m3_ = input.readInt32(); break; } default: { if (!parseUnknownField( input, unknownFields, extensionRegistry, tag)) { done = true; } break; } } } |
optional 일 때 추가되는 것들
default | optional |
private int m1_; public int getM1() { return m1_; } public Builder setM1(int value) { m1_ = value; onChanged(); return this; } public Builder clearM1() { m1_ = 0; onChanged(); return this; } |
private int bitField0_; private int m2_; public boolean hasM2() { return ((bitField0_ & 0x00000001) != 0); } public int getM2() { return m2_; } public Builder setM2(int value) { bitField0_ |= 0x00000001; m2_ = value; onChanged(); return this; } public Builder clearM2() { bitField0_ = (bitField0_ & ~0x00000001); m2_ = 0; onChanged(); return this; } |
'Develop' 카테고리의 다른 글
몽고에 저장되는 json에 쓸수 있는 정규 표현식 (0) | 2023.08.10 |
---|---|
WebClient 에러 처리 (0) | 2023.01.10 |
젠킨스 파이프라인에서 다른 job 실행 (0) | 2022.04.01 |
mysql rows to columns (0) | 2021.10.21 |
DocumentDB failover 장애 시간 (0) | 2021.09.28 |