Java로 Google Protocol Buffer 이용해보기

Jake Seo·2021년 1월 13일
0

네트워크

목록 보기
4/16

Java로 Google Protocol Buffer 이용해보기

개요

언어에 구애받지 않는 데이터 포맷인 Google Protocol Buffer를 살펴보자. 프로토콜이 있는 파일을 정의하고 그 프로토콜을 이용해서, Java, C++, C#, Go, Python과 같은 언어로 된 코드를 만들어낼 수 있다.

메이븐 의존성 추가하기

protobuf-java 의존성을 입력해준다.

프로토콜 정의

protobuf 포맷에서 매우 간단한 프로토콜을 정의할 수 있다.

message Person {
  required string name = 1;
}

위는 name이라는 간단한 문자열 필드 하나를 가진 Person 타입의 간단한 메세지 프로토콜이다.

프로토콜 정의를 좀 더 복잡한 형태로 한 것을 한번 보자. 우리가 Person의 상세한 정보를 protobuf 포맷으로 적용할 필요가 있을 때는 다음과 같다.

package protobuf;

option java_package = "com.jakeseo.protobuf";
option java_outer_classname = "AddressBookProtos";

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;
  
  repeated string numbers = 4;
}

message AddressBook {
  repeated Person people = 1;
}

우리 프로토콜은 두개의 데이터 타입을 포함한다: PersonAddressBook이다. 코드를 생성한 이후에, 위의 클래스들은 AddressBookProtos라는 클래스의 하위 클래스로 들어갈 것이다.

필요로 되는 필드(없으면 Exception을 일으키는)를 정의하고 싶을 때, 우리는 꼭 required 키워드를 사용해야 한다.

optional 키워드와 함께 필드를 만들면, 꼭 필요로 되지는 않는다는 의미가 된다. repeated 키워드는 배열 형태를 저장할 때 입력한다.

모든 필드는 인덱싱 된다. 1로 표기된 필드는 바이너리 파일의 첫번째 필드로서 저장된다. 2로 표기된 필드는 다음 필드가 된다. 이렇게 숫자를 표기하는 것은 우리 필드가 메모리에 어떻게 저장될지에 대해 제어할 수 있게 해준다.

Protobuf 파일로 자바 코드 생성하기

일단 protobuf 파일을 작성하고 나면, 우리는 그 파일로부터 코드를 생성할 수 있다.

먼저 protobuf 설치 링크여기에서 protobuf를 다운받고,

protoc -I=. --java_out=. addressbook.proto 와 같이 명령어를 입력하면 아래와 같이 자바 파일이 생성된다.

protoc 명령어가 addressbook.proto 파일로부터 Java 출력 파일을 만들어낸다. -option을 이용하여 proto파일이 어디에 위치할지 정할 수 있다. java-out은 어디에 저장될지를 정하는 것을 도와준다.

생성된 클래스는 getter, setter, constructor를 갖고 있다. 그리고 정의된 메세지를 위한 빌더도 갖고 있다. 또한 생성된 클래스는 protobuf 파일을 저장하기 위한 메소드와 binary 파일에서 자바 클래스 파일로 역직렬화 할 수 있는 메소드와 같은 유틸 메소드도 갖고 있다.

Protobuf로 정의된 메세지의 인스턴스 만들기

Builder를 이용해서 테스트 해보았다. 메세지 타입에 있는 newBuilder()라는 메소드를 이용해서 테스트해볼 수 있다. 모든 required 필드를 작성한 이후에 build() 메소드를 호출하면, Person 클래스를 만들수 있다.

Protobuf 직렬화와 역직렬화

일단 Person 클래스의 인스턴스를 만들면, 생성된 프로토콜과 호환되는 binary format으로 디스크에 저장을 하고 싶을 것이다. Addressbook 클래스의 인스턴스를 만들고, 해당 오브젝트에 Person 을 하나 추가하고 싶다고 가정해보자.

우리는 다음과 같은 코드로 객체를 디스크에 저장이 가능하다. 자동생성된 writeTo() 유틸 메소드가 있다.

AddressBookProtos.AddressBook addressBook
  = AddressBookProtos.AddressBook.newBuilder().addPeople(person).build();
FileOutputStream fos = new FileOutputStream(filePath);
addressBook.writeTo(fos);

해당 메소드를 실행한 이후에, 오브젝트가 직렬화되어 binary format이 되고 디스크에 저장된다. 데이터를 다시 불러오고 싶다면, 역직렬화를 거쳐서 다시 AddressBook 오브젝트로 가져오면 되는데, 이 때 mergeFrom() 메소드를 사용할 수 있다.

난 다음과 같은 테스트 코드들을 작성했고, 잘 동작했다.

결론

Google Proto Buffer를 사용해보았다.

간단한 프로토콜을 만들어보았고, 그 프로토콜을 이용해서 자바 인스턴스를 생성해보기도 했고, binary 파일로 직렬화도 해보고 그걸 다시 역직렬화도 해봤다.

레퍼런스 : https://www.baeldung.com/google-protocol-buffer

profile
풀스택 웹개발자로 일하고 있는 Jake Seo입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. 프론트엔드: Javascript, React 백엔드: Spring Framework에 관심이 있습니다.

0개의 댓글