업무에서 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
https://github.com/trustin/os-maven-plugin
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
참고
https://github.com/protocolbuffers/protobuf/tree/main/java
https://developers.google.com/protocol-buffers/docs/overview
'기타 학습' 카테고리의 다른 글
[Protocol Buffer] 프로토콜 버퍼를 사용한 Spring REST API 구현 (HTTP 통신) (0) | 2022.12.06 |
---|---|
[AWS] Access Key노출 (AWSCompromisedKeyQuarantineV2 해결) (1) | 2022.11.30 |
[Flutter] Flutter widget (위젯 개념/ State) (0) | 2022.09.10 |
[Flutter] Dart 문법3 (제어문/ 조건문/ 반복문) (0) | 2022.09.09 |
[Flutter] Dart 문법 2 (상속/ 인터페이스/ Cascade Operator) (0) | 2022.09.08 |
댓글