본문 바로가기

소질없는 개발

구글 profobuf 사용하기

protobuf

  • 구글에서 개발한 오픈소스 직렬화 라이브러리
  • 메시지 직렬화, 역직렬화를 통해 네트워크 통신, 데이터 저장에 사용
  • 데이터 구조와 서비스를 proto 스키마 파일에 저장하고 원하는 언어로 컴파일하면 자동으로 코드 생성
  • java, Erlang, javascript, Lua, Perl, PHP, R, Scala, Swift, python, c++, go, ruby, c# 등 다양한 언어 지원
  • json 을 사용하는 것보다 데이터 크기를 줄이고 전반적인 성능 향상을 기대할 수 있음
  • 전력, 네트워크 컴퓨팅 파워가 부족한 임베디드 기기의 경우 도움이 됨

 

json vs protobuf

구분특징

json

  • 사람이 읽고 쓸 수 있어 개발과 디버깅이 편리함
  • 스키마에 대한 지식이 없어도 사용 가능
protobuf
  • 처리 속도가 빠르고 데이터 압축률이 좋음
  • 이진데이터이므로 사람이 읽을 수 없음
  • 스키마에 대한 지식 필요

 

설치

 

Language Guide (proto3)

https://developers.google.com/protocol-buffers/docs/proto3

  • 메시지 타입 정의 : .proto 파일 생성
  • protobuf 의 패키지가 아닌 다른 패키지명 지정 가능, 언어별로 다르게 지정 가능 (지정하지 않으면 protobuf 패키지를 따름)
  • 클래스명도 원하는 이름으로 변경 가능 (지정하지 않으면 .proto 파일명을 따름)
Message.proto
syntax = "proto3";
 
option java_package="com.test.common.protobuf";
option java_outer_classname = "Message";
import "Command.proto";
 
message MessageBase {
    string data = 1;
}


Style Guide

  • Message 및 Field name
    • Message name :CamelCase (with an initial capital) 
    • Field name : underscore_separated_names
    • .proto 정의
      message SongServerRequest {
        required string song_name = 1;
      }
       
      컴파일 결과
      C++:
        const string& song_name() { ... }
        void set_song_name(const string& x) { ... }
       
      Java:
        public String getSongName() { ... }
        public Builder setSongName(String v) { ... }
  • Enums
    • Enum 타입명 :CamelCase (with an initial capital) 
    • Enum 타입값 : CAPITALS_WITH_UNDERSCORES
    • 각 Enum 값은 세미콜론(;) 으로 구분
  • Service
    • RPC Service 를 정의할 경우, 서비스명과 RPC 메소드명 모두 CamelCase (with an initial capital) 
    • service FooService {
        rpc GetSomething(FooRequest) returns (FooResponse);
      }

 

Scalar Value Types

.proto 파일에 .proto Type 을 정의하면 자동 생성된 클래스에 각 언어별로 지정된 타입이 정의됨

.proto TypeNotesC++ TypeJava TypePython Type[2]Go TypeRuby TypeC# TypePHP Type
double doubledoublefloatfloat64Floatdoublefloat
float floatfloatfloatfloat32Floatfloatfloat
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32Fixnum or Bignum (as required)intinteger
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/long[3]int64Bignumlonginteger/string[5]
uint32Uses variable-length encoding.uint32int[1]int/long[3]uint32Fixnum or Bignum (as required)uintinteger
uint64Uses variable-length encoding.uint64long[1]int/long[3]uint64Bignumulonginteger/string[5]
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32Fixnum or Bignum (as required)intinteger
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/long[3]int64Bignumlonginteger/string[5]
fixed32Always four bytes. More efficient than uint32 if values are often greater than 228.uint32int[1]int/long[3]uint32Fixnum or Bignum (as required)uintinteger
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 256.uint64long[1]int/long[3]uint64Bignumulonginteger/string[5]
sfixed32Always four bytes.int32intintint32Fixnum or Bignum (as required)intinteger
sfixed64Always eight bytes.int64longint/long[3]int64Bignumlonginteger/string[5]
bool boolbooleanboolboolTrueClass/FalseClassboolboolean
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringStringstr/unicode[4]stringString (UTF-8)stringstring
bytesMay contain any arbitrary sequence of bytes.stringByteStringstr[]byteString (ASCII-8BIT)ByteStringstring

You can find out more about how these types are encoded when you serialize your message in Protocol Buffer Encoding.
[1] In Java, unsigned 32-bit and 64-bit integers are represented using their signed counterparts, with the top bit simply being stored in the sign bit.
[2] In all cases, setting values to a field will perform type checking to make sure it is valid.
[3] 64-bit or unsigned 32-bit integers are always represented as long when decoded, but can be an int if an int is given when setting the field. In all cases, the value must fit in the type represented when set. See [2].
[4] Python strings are represented as unicode on decode but can be str if an ASCII string is given (this is subject to change).
[5] Integer is used on 64-bit machines and string is used on 32-bit machines.

 

Default Values

Type기본값비고
stringempty string 
byteempty bytes 
boolfalse 
numeric typezero 
enumfirst defined enum value0
message fieldnot set

language-dependent

generated code guide


.proto 자바 컴파일

protoc 다운로드 : https://github.com/google/protobuf/releases (하단, 2018.06.18 현재 최신 protoc-3.5.1-win32.zip)

protoc --proto_path=src --java_out=build/gen src/foo.proto
  • 자바 컴파일을 위해 --java_out 지정
  • .proto 파일 당 하나의 .java 파일 생성
  • 경로에 포함된 / 는 패키지 구조 . 으로 변경됨 


자바 코드에서 사용

public MessageBase.Builder createData(String data){
    MessageBase.Builder msg = MessageBase.newBuilder();
    msg.setData(data);
    return msg;
}