코딩관계론

ProtoBuf (Protocol Buffer, 프로토콜 버퍼) 본문

개발

ProtoBuf (Protocol Buffer, 프로토콜 버퍼)

개발자_티모 2023. 7. 27. 16:43
반응형

Protocol Buffer는 google 사에서 개발한 구조화된 데이터를 직렬화하는 기법입니다.

 

직렬화(Serialization)란 데이터를 메모리에 저장된 형식에서 다른 형식으로 변환하는 작업을 의미합니다. 프로그램에서 사용되는 데이터는 변수, 객체 등의 형태로 메모리에 저장되어 있지만, 이 데이터를 네트워크를 통해 전송하거나 파일로 저장하기 위해서는 텍스트 형식 또는 이진 형식으로 변환해야 합니다. 이때, Protocol Buffer는 이진 형식의 직렬화를 수행하여 데이터를 효율적으로 표현합니다.

 

 

Proto File

1)Message and Field

Proto File에서는 주고 받는 data들을 message 라는 것으로 정의합니다. 이 메시지는 여러가지 타입의 필드로 구성됩니다. 아래 예시로 query, page_number, result_per_page 라는 필드를 가지는 SearchRequest 라는 메시지를 정의해보았습니다.

syntax = proto3

message SearchRequest {
  string query = 1
  int32 page_number = 2
  int32 result_per_page = 3
}

 

2) Naming

message 이름은 CamelCase 형태, field 이름은 under_bar 형태로 사용할 것을 권장하고 있습니다. 유의할 점은 field 이름은 숫자로 시작할 수 없다는 점인데요. 숫자를 표기해야 할 경우 문자 뒤에다가 표기 해야합니다.

ex) query_1 (o) / 1_query(x)

3) Field Tag

메세제에 정의된 필드들은 각각 고유한 번호를 가지고 있는데 이는 Encoding 이후 binary data에서 필드를 식별하는데 사용됩니다.

 

Field Tage는 최소 1, 최대 최대 536,870,911(=229–1) 로 지정 가능하며, 19000 ~ 19999는 프로토콜 버퍼 구현을 위해 reserved 된 값이므로 사용할 수 없습니다.

 

필드 번호가 1~15일 때는 1byte, 16~2047은 2byte를 Tag로 가져가게 되는데요. 때문에 자주 호출되는 필드에 대해선 1~15로 지정해두는 것이 좋습니다. 그런데 여기서 한 가지 의문이 드는데요, 1byte는 8bit라서 255까지 표현이 가능한데 필드 번호로 쓰일땐 왜 1~15 까지만 표현될까요? 

 

proto2 VS proto3

위 예제에서는 첫 줄에 syntax = “proto3”을 지정해줌으로써 proto version 3의 규약을 따르겠다고 선언했습니다. 이를 명시하지 않으면 default로 version2 문법을 따르게 됩니다. 아래와 같이 지원 언어도 다르지만, message 작성 시 field rule 지정 등 문법에도 차이가 나타납니다.

 

- Proto2 지원 언어 : C++, Java, Python, Go

- Proto3 지원 언어 : C++, Java, Python, Go, Ruby, Objectice-C, C#, JavaScript, PHP, Dart

 

Proto File Field Rule

- required : 필수로 가져야 할 필드 (only use proto2)

- optional : 해당 필드를 가지지 않거나 하나만 가짐 (only use proto2)

- repeated : 임의 반복 가능한 필드 (번호 및 값의 순서는 보존)

* [packed=true] 옵션 : key-value 쌍 형태에서 value만 반복

 

proto3에선 required, optional은 사라지고, repeated 만 사용됩니다. proto2도 계속 기술지원이 되고 있으나, 지원 언어 및 새로운 기능 지원을 위해 proto3을 사용할 것을 권장합니다.

 

위와 같이 repeated rule을 주게되면 Field를 배열의 형태로도 사용할 수 있게 됩니다. 필드는 Key-Value 구조로 저장되어 repeated field를 사용할 때도 key가 계속 붙게되는데, reqeated 뒤에 packed 옵션을 주면 value만 반복하게끔 할 수 있어요.

어차피 필드 번호는 바뀌지 않으니 되도록 이 옵션을 주면 보다 효율적인 Enconding이 되겠네요.

 

Package

package는 message type 이름을 중첩없이 구분할 때 사용합니다. 메시지 사용 시 package를 명시함으로써 필드와 명확히 구분해주죠. 아래 예제에서는 Open이라는 message를 타입으로 하는 field 이름을 open으로 주어 모호한 정의를 package로 구분하였습니다. 사실 foo.bar라는 package를 굳이 쓰지 않는다고 사용이 불가한 것은 아니지만, 구성 메시지가 많다면 명확하게 구분될 수 있게 명시해 주는 것이 좋겠습니다.

 

Service

Service는 RPC를 통해 서버가 클라이언트에게 제공할 함수의 형태를 정의합니다. 서비스명과 RPC 메소드명 모두 CamelCase 형태를 권장하네요. 옵션을 주지 않으면 단일 요청/응답으로 동작하지만, stream 옵션을 주면 RPC를 구현할 수 있습니다.

반응형

'개발' 카테고리의 다른 글

타임딜 서비스 개발기  (2) 2024.07.25
최적의 PK를 찾아서  (0) 2024.07.25
Git Branch 관리 전략  (0) 2024.07.17
객체지향이란 무엇인가  (0) 2024.06.01
gRPC 개념  (0) 2023.07.25