Protobuf란?

protobuf (프로토콜버퍼)

  • 프로토콜 버퍼는 데이터를 직렬화하기 위한 유연하고 효율적이며 자동화 된 메커니즘
  • XML보다 작지만 더 빠르고 단순
  • 데이터를 한 번 구성하는 방법을 정의한 다음 생성 된 소스 코드를 사용 - 예전에 사용해본 AIDL과 느낌이 비슷 : https://developer.android.com/guide/components/aidl?hl=ko
  • 다양한 데이터 스트림에서 다양한 언어로 다양한 구조의 데이터를 쉽게 읽고 쓸 수 있음.
  • 옛날 버전으로 컴파일 된 배포 된 프로그램을 중단하지 않고도 데이터 구조를 업데이트 할 수도 있다고 함.

protobuf cli 설치

 ~/Downloads/protoc-3.10.1-osx-x86_64$ ll
total 8
drwxr-x---@ 3 dobby  staff    96B 10 29 11:10 bin
drwxr-x---@ 4 dobby  staff   128B 11 11 15:14 include
-rw-r-----@ 1 dobby  staff   724B 10 29 11:10 readme.txt

장점

  • 미리 serialize, deserialze에 대해서 선언해 두었기 때문에 payload 의 크기를 월등히 줄일 수 있음 (다른 rpc protocol과 비슷하나 header를 미리 정의하므로 header 영역에 대해서는 좀 더 가볍게 설계 할 수 있지 않을까)
  • go, javascript, java, kotlin 등 여러가지 언어 지원가능
  • API 문서화 대신 .proto 만 공유하면 가장 최근의 api interface를 공유 할 수 있음

단점

  • 한번은 컴파일을 해야 java 파일 또는 header 파일이 생성되므로 귀차니즘 증가
  • protocol body 만 보고 무슨 내용인지 알기 힘들다. 이건 아직 안해봤는데 해봐야지..

person.proto 예시

syntax = "proto3";

package tutorial;

option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";

message Person {
  required string name = 1;
  required int32 id = 2;
  string email = 3; //optional in proto3

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}

protoc 컴파일

protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/addressbook.proto
../protoc -I=./ --java_out=./ ./person.proto

생성 된 protoc API

  • 컴파일하면 다음과 같은 파일이 생성됨
// required string name = 1;
public boolean hasName();
public String getName();

// required int32 id = 2;
public boolean hasId();
public int getId();

// optional string email = 3;
public boolean hasEmail();
public String getEmail();

// repeated .tutorial.Person.PhoneNumber phones = 4;
public List<PhoneNumber> getPhonesList();
public int getPhonesCount();
public PhoneNumber getPhones(int index);

// required string name = 1;
public boolean hasName();
public java.lang.String getName();
public Builder setName(String value);
public Builder clearName();

// required int32 id = 2;
public boolean hasId();
public int getId();
public Builder setId(int value);
public Builder clearId();

// optional string email = 3;
public boolean hasEmail();
public String getEmail();
public Builder setEmail(String value);
public Builder clearEmail();

// repeated .tutorial.Person.PhoneNumber phones = 4;
public List<PhoneNumber> getPhonesList();
public int getPhonesCount();
public PhoneNumber getPhones(int index);
public Builder setPhones(int index, PhoneNumber value);
public Builder addPhones(PhoneNumber value);
public Builder addAllPhones(Iterable<PhoneNumber> value);
public Builder clearPhones();

example

  • java파일이 생성되면 다음과 같이 사용가능함

    Person dobby =
    Person.newBuilder()
    .setId(1234)
    .setName("dobby")
    .setEmail("admin@dobby.work")
    .addPhones(
      Person.PhoneNumber.newBuilder()
        .setNumber("123-4567")
        .setType(Person.PhoneType.HOME))
    .build();

usecase

reference


dobby
Written by@dobby
The beautiful thing in the world. the most precious thing in the universe.