안녕하세요. 오늘은 gRPC의 2번째 시간입니다. 오늘은 gRPC에서 사용하는 IDL(Interface Defintion Language)인 protocol buffer을 실제로 사용해보도록 하겠습니다.
기본
프로토콜 버퍼(protocol buffer)는 .proto
의 확장자를 파일명으로 가집니다. 그리고 내부의 기본적인 구성은 아래와 같습니다.
syntax = "proto3";
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 result_per_page = 3;
}
위의 구성을 통해 알 수 있는 내용을 보면 아래와 같습니다.
- 첫 라인에는 syntax로
proto3
를 사용한다고 명시해줍니다. 명시하지않으면 기본 값으로proto2
의 문법이 적용되기때문에 필수적입니다. - message는 모델을 만드는 키워드입니다. qeury, page_number, result_per_page라는 3개의 필드를 가지는 모델인 SearchRequest에 대해서 정의하고 있다고 생각하시면 됩니다.
- 프로토콜 버퍼에서 모든 필드는 scalar type을 가집니다. 위 에제는 2개의 정수 변수와 1개의 문자열 변수를 선언했습니다.
- 모든 필드는 고유한 숫자(unique number)를 하나씩 가집니디. 프로토콜 버퍼는 통신시 byte stream으로 전달되기 때문에 직렬화/역직렬화시 이 숫자는 순서를 나타내며 중요하며 필수적입니다.
위의 예제는 프로토콜 버퍼를 사용할 때 가장 기본이되는 구성을 가지고 있습니다. 여기에 조금 더 추가한 아래의 예제를 보도록 하겠습니다.
syntax = "proto3";
/*
* 요청 Model
*/
message SearchRequest {
string query = 1; // 이렇게도 주석을 사용할 수 있어요
int32 page_number = 2;
int32 result_per_page = 3;
}
/*
* 응답 Model
*/
message SearchResponse {
int32 code = 1;
enum Corpus {
UNIVERSAL = 0;
WEB = 1;
IMAGES = 2;
LOCAL = 3;
NEWS = 4;
PRODUCTS = 5;
VIDEO = 6;
}
Corpus corpus = 3;
}
위의 구성을 통해 알 수 있는 내용을 보면 아래와 같습니다.
- 프토토콜 버퍼는
//
키워드를 이용하여 1줄짜리 주석을 사용할 수 있으며,/**/
를 이용하여 여러줄 짜리 주석을 사용할 수 있습니다. 이 주석은 java 등 다른 언어로 만들어질때 함께 들어갑니다. - enum 타입을 지정할 수 있습니다. 위 코드에서는
Corpus
enum 타입을 정의한 후 사용하고 있습니다. enum 또한 고유한 0을 포함한 자연수의 숫자를 필요로 합니다. enum에option allow_alias = true;
를 추가하면 숫자를 겹치게하여 사용할 수도 있습니다.
더 나아가기
또 다른 프로토콜 버퍼 예제를 하나 보도록 하겠습니다.
message SearchResponse3 {
repeated Result results = 1;
}
message Result {
string url = 1;
string title = 2;
repeated string snippets = 3;
map<string, string> projects = 4;
}
- 프로토콜 버퍼는 내부에 또 다른 message를 포함할 수 있습니다. 위의 예제에서는 SearchResponse3 모델에서 Result 모델을 참조하고 있습니다.
- SearchResponse3에서 result와 Result에서 snippets 모두
repeated
라는 키워드를 사용하고 있습니다. 해당 키워드릴 사용하면 List로써 필드를 다루게 됩니다. - Result 모델에
map<string, stirng>
을 타입으로 사용한 것을 보실 수 있습니다. 프로토콜 버퍼에서는 맵 자료구조를 지원합니다. 이 타입은 repeated 키워드는 지원하지 않기 때문에 주의가 필요합니다.
그 외
기본값
- string 타입은 empty string을 기본값으로 가집니다.
- byte 타입은 empty byte를 기본값으로 가집니다.
- bool 타입은 false를 기본값으로 가집니다.
- 숫자형 타입은 0을 기본값으로 가집니다.
- enum 타입은 첫번째 값을 기본값으로 가집니다.
- message 타입은 기본값이 없습니다. 이에 대한 처리는 각각 언어에 따라 달라집니다.
package
프로토콜 버퍼에서 package를 선언할 수 있습니다. 이렇게 선언하면 해당 파일에 선언되는 message 들은 java에서 그 패키지에 위치하게 됩니다.
package me.sabarada;
Service 정의
RPC에서 프로토콜 버퍼를 사용하기 위해서는 service의 정의가 필요합니다. service 정의에 의해서 통신에 필요한 구성요소들이 만들어지게 됩니다.
service HelloService {
rpc SayHello (HelloRequest) returns (HelloResponse);
rpc LotsOfReplies (HelloRequest) returns (stream HelloResponse);
rpc LotsOfGreetings (stream HelloRequest) returns (HelloResponse);
rpc BidiHello (stream HelloRequest) returns (stream HelloResponse);
}
Option
option은 프로토콜 버퍼에서 추가적으로 제공하는 기능입니다. 이 기능은 각자 언어에 따라 달라질 수 있습니다. 여기서는 java에서 주로 사용되는 옵션 2개를 설명드리겠습니다. java_outer_classname
옵션은 java에서 생성될 클래스의 이름을 나타냅니다. 기본적으로 java로 변환하면 하나의 파일이 하나의 클래스로 변환됩니다. 그 class 파일의 이름이라고 보시면됩니다.
option java_outer_classname = "Sample"; // options --> 클래스 이름
public final class Sample {
private Sample() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface SearchRequestOrBuilder extends
// @@protoc_insertion_point(interface_extends:me.sabarada.SearchRequest)
com.google.protobuf.MessageOrBuilder {
[...하략...]
다음 옵션은 하나의 proto 파일에서 설정된 값을 여러개의 클래스 파일로 나누어서 생성하게끔하는 옵션입니다. java_multile_files 옵션은 기본적으로 false이며 true로 변경하면 여러개의 클래스 파일로 하나의 proto 파일을 생성합니다.
option java_multiple_files = true; // option --> 1개의 proto 파일에서 여러개의 클래스 파일이 생성 가능
마무리
오늘은 이렇게 프로토콜 버퍼에 대해서 알아보는 시간을 가져보았습니다.
감사합니다.
참조
'infra > network' 카테고리의 다른 글
[Network] Apache HttpClient의 설정으로 알아보는 클라이언트 관점의 네트워크 속성들 (0) | 2024.05.17 |
---|---|
[gRPC + java or kotlin] gRPC를 직접 구현재보자 - 공통 모델편 (0) | 2021.07.31 |
[gRPC] gRPC에 대해서 알아보자 - 기본 컨셉편 (0) | 2021.07.24 |
[HTTP] HTTP Cache - 프로세스와 기본 헤더 (2) | 2021.02.04 |
[HTTP] HTTP 메시지 분석 하기 (0) | 2021.01.28 |
댓글