본문 바로가기
기타 학습

[Protocol Buffer] 프로토콜 버퍼 (개념 / 입문 / Spring Boot Maven 실습)

by 비전공자 기록광 2022. 11. 28.
반응형

업무에서 TCP통신과 모드버스로 프로토콜 버퍼까지 이야기가 흘러 gRPC와 함께 공부하게 되었다.

네트워크에 자신 없는 터라 좀 이해하는데 좀 오래 걸렸다... 😕

네트워크 공부 다시해야지..

 

프로토콜 버퍼 Protocol Buffer 

구글이 공개한 직렬화 데이터 구조

 

It’s like JSON, except it's smaller and faster

 

특징

  • 다양한 언어에서 호환 가능
    • Java, Kotlin, C++, C#, Python, Go 등
  • 빠른 파싱 (바이너리 전송)
  • 간편한 데이터 저장소
  • 클래스 자동 생성 통한 기능성 최적화

 

프로토콜 버퍼를 추천하지 않는 경우

  • 전체 메시지가 MB를 초과하는 경우
  • 비 객체 지향 언어를 사용하는 경우

 

작동 방법

 

1. .proto 파일 정의

2. proto compiler 통해 source 파일 생성

3. proto compiler 통해 파일 인코딩, 디코딩

 

 

Java + Spring Boot + Maven 실습

proto 파일을 생성하고 읽고 쓰는 간단한 실습을 진행해보겠다.

 

프로토콜 버퍼를 사용하는데 가장 먼저 필요한 것은 protobuf compiler 설치이다.

 

 

릴리즈 페이지에서 본인의 환경에 맞는 컴파일러를 다운받아 환경변수 적용까지 해준다.

 

cmd창에서 protoc --version 로 잘 다운 받아졌는지 확인할 수 있다.

 

새로운 스프링부트 프로젝트를 생성해준다.

오직 protobuf-java 만 추가해줬다.

 

Pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<dependencies>
 
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.21.9</version>
        </dependency>
 
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
cs

 

 

Person.proto

이제 .proto 파일을 정의해주면 된다.

 

resources 밑에 proto 디렉토리를 새로 만들고 그 안에 Person.proto 파일을 만들어줬다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
syntax = "proto3";
 
package com.google.protocolbuffertest.domain;
 
option java_package = "com.google.protocolbuffertest.domain";
option java_outer_classname = "PersonInfo";
 
message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;
}
 
message AddPerson {
  repeated Person people = 1;
}
cs

 

자세한 proto3 문법은 google docs에 잘 나와있다.

message가 우리가 직렬화할 정보의 구조 단위이다.

 

나는 Person이라는 정보를 만들거고 id, name, emial의 값들을 갖는다. 

또 AddPerson라는 구조 정보를 만들건데 이는 Person을 배열 형태로 저장하기 위해 repeated로 정의했다.

 

그리고 이 proto 파일을 source 파일로 컴파일 한 후의 패키지 정보와 이름을 각각 java_package,  java_outer_classname으로 정의해줬다.

 

이렇게 정의된 .proto 파일을 source 파일로 생성하기 위해서 터미널에 명령을 날리면 된다.

 

$ protoc --java_out=${OUTPUT_DIR} path/to/your/proto/file

 

이렇게 명령어를 날려주면 바로 java_package에서 정의한 경로대로 PersonInfo 클래스 파일이 생성된다.

 

 

 

하지만 매번 이렇게 명령어를 날려주고 생성해주기 귀찮다.

그렇다면 빌드 도구를 이용해 빌드될 때 자동으로 protocol compiler까지 해주는 코드를 추가해주면 된다.

 

 

찾은 바로 이렇게 두가지를 많이 쓰는 것 같은데 나는 os-maven-plugin을 사용해줬다.

 

https://github.com/os72/protoc-jar-maven-plugin

 

GitHub - os72/protoc-jar-maven-plugin: Protocol Buffers protobuf maven plugin - based on protoc-jar multi-platform executable pr

Protocol Buffers protobuf maven plugin - based on protoc-jar multi-platform executable protoc JAR - GitHub - os72/protoc-jar-maven-plugin: Protocol Buffers protobuf maven plugin - based on protoc-j...

github.com

https://github.com/trustin/os-maven-plugin

 

GitHub - trustin/os-maven-plugin: A Maven plugin that sets various useful properties detected from ${os.name} and ${os.arch} pro

A Maven plugin that sets various useful properties detected from ${os.name} and ${os.arch} properties. - GitHub - trustin/os-maven-plugin: A Maven plugin that sets various useful properties detecte...

github.com

 

 

build에 os-maven-plugin을 추가해주고 proto 파일을 찾을 경로, source 파일을 만들어줄 경로를 정의해줬다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.21.9</version>
        </dependency>
 
    </dependencies>
 
    <build>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.1</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
            <groupId>org.xolstice.maven.plugins</groupId>
            <artifactId>protobuf-maven-plugin</artifactId>
            <version>0.6.1</version>
            <extensions>true</extensions>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.21.9:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.25.0:exe:${os.detected.classifier}</pluginArtifact>
                    <clearOutputDirectory>false</clearOutputDirectory>
                    <protoSourceRoot>${project.basedir}/src/main/resources/proto</protoSourceRoot>
                    <outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
                </configuration>
            </plugin>
        </plugins>
    </build>
cs

 

이렇게 추가해주면

maven install 만 해줘도 PersonInfo 파일이 똑같이 생성된다.

 

 

 

이제 이 PersonInfo를 통해 읽고 쓰기를 해본다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.google.protocolbuffertest;
 
import com.google.protocolbuffertest.domain.PersonInfo;
 
public class ProtocolbuffertestApplication {
 
    public static void main(String[] args) {
 
        PersonInfo.Person person1 = PersonInfo.Person.newBuilder().setId(1).setName("홍길동").setEmail("hong11@test.com").build();
        PersonInfo.Person person2 = PersonInfo.Person.newBuilder().setId(2).setName("고길동").setEmail("go22@test.com").build();
        PersonInfo.Person person3 = PersonInfo.Person.newBuilder().setId(3).setName("오길동").setEmail("oh33@test.com").build();
 
        PersonInfo.AddPerson people = PersonInfo.AddPerson.newBuilder().addPeople(person1).addPeople(person2).addPeople(person3).build();
 
        for (PersonInfo.Person p : people.getPeopleList()) {
            System.out.println(p.getId());
            System.out.println(p.getName());
            System.out.println(p.getEmail());
            System.out.println(p.getAllFields());
            System.out.println(p.toByteString());
        }
    }
 
}
 
cs

 

main 함수에서 Person 을 쓰고 배열 형태로 쓰고, 그걸 또 읽는 코드를 작성했다.

이대로 실행하면 이렇게 Person이 찍히는 걸 볼 수 있다.

 

 

 

 

🌞 gradle인 경우는 여기에 잘 정리되어 있다.

GitHub - google/protobuf-gradle-plugin: Protobuf Plugin for Gradle

 

GitHub - google/protobuf-gradle-plugin: Protobuf Plugin for Gradle

Protobuf Plugin for Gradle. Contribute to google/protobuf-gradle-plugin development by creating an account on GitHub.

github.com

 

 


 

참고

https://github.com/protocolbuffers/protobuf/tree/main/java

 

GitHub - protocolbuffers/protobuf: Protocol Buffers - Google's data interchange format

Protocol Buffers - Google's data interchange format - GitHub - protocolbuffers/protobuf: Protocol Buffers - Google's data interchange format

github.com

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

 

Overview  |  Protocol Buffers  |  Google Developers

Protocol buffers provide a language-neutral, platform-neutral, extensible mechanism for serializing structured data in a forward-compatible and backward-compatible way. It’s like JSON, except it's smaller and faster, and it generates native language bind

developers.google.com

 

 

반응형

댓글