Protocol Buffers(protobuf) in Java
공부하면서 연습한 코드는 깃허브에 올려두었습니다
프로토콜 버퍼 (Protocol Buffers, Protobuf)는 구글이 개발한 구조화된 데이터를 직렬화하는 방식입니다.
프로토콜 버퍼를 사용하는 이유
데이터를 직렬화(serialize)하고 구조화된 데이터를 주고 받을 때 다음과 같은 방법을 생각해볼 수 있습니다.
1. Java Serialization
- 다른 언어와 데이터를 주고 받을 때 잘 동작하지 않습니다
2. ad-hoc way (특별한 목적을 위해서 정의하고 사용하는 방식)
- 데이터를 특정한 문제를 풀기 위해 (예를들어 encoding 4 ints로 만드는 경우 ex. 12:3:-23:67)
- 내부에서 사용하려는 목적으로 간단하게 ad-hoc 방식은 간단한 메시지의 경우에는 빠르고 좋은 결과를 낼 수 있지만
- 복잡한 메시지의 경우에는 메시지를 만들어 내기가 어렵다
- 범용성도 떨어진다
3. XML, JSON 형식
- 사람이 읽기 좋다
- 언어별로 라이브러리가 잘 되어있다
- verbose해서 메모리 공간을 많이 잡아먹고 encoding/decoding 할 때 퍼포먼스 측면에서 자원을 많이 쓴다
프로토버퍼는 .proto 파일을 작성하고 compiler를 실행하면 해당 언어로 encoding, parsing을 해주는 클래스 파일을 생성해줍니다. 유명한 언어 대부분을 지원하고 있습니다 (C++, C#, GO, Java, Kotlin, Python, Dart,,)
Protobuf2 문법
syntax = "proto2";
message Person {
optional string name = 1;
optional int32 id = 2;
optional string email = 3;
}
message AddressBook {
repeated Person people = 1;
}
Person, AddressBook은 메시지 클래스입니다
"=1", "=2"는 binary encoding에 사용되는 태그입니다
- optional: 선택적 필드입니다.
- repeated: 반복해서 등장하는 필드입니다 (0번 이상 반복). 순서가 보장됩니다.
- required: 필수 필드입니다
required 필드는 한번 사용되면 나중에 칼럼을 제거하거나 변경하기가 어렵기 때문에 매우 신중하게 사용해야합니다. 그래서 구글 사내에서는 required 선호도가 매우 떨어집니다. protobuf3 문법에서는 required가 없습니다.
(개인적인 생각: 일리가 있는 생각입니다만 모든 칼럼을 optional로 사용하면 해당 필드가 필수인지 선택인지 알 수 있는 방법이 없다고 생각합니다. 칼럼이 수정/삭제가 있으면 전파되는 것은 다른 방법으로 처리하면 좋을 거 같습니다. 즉, 두개는 다른 문제로 접근했으면 더 좋겠다고 생각합니다)
Compiling Protocol Buffers
1. protoc 설치
(1) Mac
- brew install protobuf
(2) windows
- https://github.com/protocolbuffers/protobuf/releases 에서 윈도우 실행파일을 다운로드 받습니다
(protoc-3.xx.x-win64.zip)
- 환경변수에 등록합니다
2. protoc를 실행합니다
# protoc --java_out={자바 클래스를 만들 경로} {.proto 파일 경로}
protoc --java_outsrc/main/java ./src/main/java/com/example/tutorial/schema/addressbook.proto
실행결과
option java\_package = "com.example.tutorial.addressbook.domain";
으로 생성될 패키지를 설정했습니다
protoc --java\_out=src/main/java ./src/main/java/com/example/tutorial/schema/addressbook.proto
커맨드로 .protobuf를 컴파일 하면 다음과 같은 파일이 생성되고 다음과 같은 구조가 됩니다