나만의 작은 도서관

[Network] protoBuf와 직렬화/역직렬화 본문

Common/CS-네트워크

[Network] protoBuf와 직렬화/역직렬화

pledge24 2024. 6. 28. 20:24
유의사항: 해당 글은 공부한 내용을 정리하는 용도이므로, 수정이 필요할 경우 내용의 수정이 있을 수 있습니다.

protoBuf

protoBuf는 Protocol Buffer의 약자이며, Google에서 개발한 직렬화 데이터 구조이다. 효율적인 데이터 교환을 위해 설계되었으며, 특히 네트워크 통신과 저장 시스템에서 널리 사용됩니다. 이런 protoBuf는 여러 가지 데이터 구조 중 하나이기 때문에 자주 접해본 XML, JSON과 방식과 유사하다고 볼 수 있습니다. 


직렬화 (serialization)와 역직렬화( Deserialization )

protoBuf가 직렬화 데이터 구조인만큼 우선 직렬화와 반대되는 개념인 역직렬화가 무엇이지 알아야합니다.

직렬화는 객체 또는 데이터 구조를 연속적인 바이트 스트림(byte Stream)으로 변환하는 과정입니다. 이 바이트 스트림은 파일, 메모리 또는 네트워크를 통해 다른 프로그램이나 시스템으로 전달될 수 있습니다.

반대로, 역직렬화는 직렬화된 바이트 스트림을 다시 원래의 객체나 데이터 구조로 변환하는 과정입니다. 이를 통해 데이터를 저장하거나 전송한 후에 원래의 상태로 복원할 수 있습니다.

 

직렬화와 역직렬화를 사용하는 여러 방식들

 

protobuf가 아니더라도 직렬화와 역직렬화를 사용하는 방식들은 다양합니다. 방식들의 종류는 아래와 같습니다.

 

  직렬화 역직렬화
Java Serializable 인터페이스를 사용하여 객체를 직렬화. ObjectInputStream을 사용하여 객체를 역직렬화.
Python pickle 모듈을 사용하여 객체를 직렬화. pickle 모듈을 사용하여 객체를 역직렬화.
JSON, XML 데이터를 텍스트 형식으로 직렬화. 데이터를 텍스트 형식에서 객체로 역직렬화.

 


protoBuf의 장점

 

  • 효율적인 데이터 표현 및 빠른 처리 속도: 작은 크기의 바이너리 형식과 빠른 직렬화/역직렬화 덕분에 성능이 뛰어납니다.
  • 후방 호환성: 시스템을 업데이트하면서도 이전 버전의 데이터를 유지할 수 있어, 데이터 모델의 변화에 유연하게 대응할 수 있습니다.
  • 언어 및 플랫폼 독립성: 다양한 언어와 플랫폼을 지원하여 이기종 시스템 간의 통신을 용이하게 합니다.
  • 명확한 데이터 정의: 스키마 파일을 통해 데이터 구조를 명확히 정의하고, 자동 코드 생성을 통해 개발을 단순화합니다.
  • 풍부한 데이터 타입: 기본 데이터 타입과 복합 타입을 지원하여 복잡한 데이터 구조를 효과적으로 표현할 수 있습니다.
  • 우수한 성능과 확장성: 성능이 중요한 애플리케이션과 큰 규모의 데이터 처리에 적합합니다.

 

 


protoBuf 사용법

protoBuf를 사용하고 싶다면 데이터 구조를 정의해야합니다. JSON을 사용했을 때 package.json과 같이 .json확장자를 사용하듯 protoBuf는 .proto 확장자를 통해 데이터 구조를 정의합니다.

 

.proto에서 메세지 정의 예제

// person.proto

syntax = "proto3";

message Person {
// field type field name = field number
  string name = 1;
  int32 id = 2;
  string email = 3;
}
  • syntax: 버전. 위 예시에서는 proto3버전을 사용한다 선언했다.
  • message: 메세지를 정의한다. 메세지 이름과 메세지 안에 들어갈 필드를 작성하면 된다.
  • field: 메세지 안에 들어가는 필드이다. "field type field name = field number "형식으로 작성하면 된다.
  • field type:  필드 타입(string, int32등등...)
  • field name: 필드 이름
  • field number: 필드 번호이다. 다른 필드와 중복되지 않는 숫자를 넣어주면 된다.

필드 번호를 사용하는 이유

Protobuf는 데이터를 압축하여 효율적으로 저장하고 전송하는데, 이 과정에서 필드 이름 대신 필드 번호를 사용하기 때문입니다. 필드 번호를 사용하게되면 데이터를 더 작은 크기로 생성할 수 있고, 이는 전송 속도를 높이고 저장 공간을 절약하는 데 도움이 됩니다.

 

+) field Tag에서 사용해야하는 번호가 정해져있는건 아닙니다. 그저 관리와 이해를 쉽게 하기 위한 관례라고 보시면 됩니다. 

 

protoBuf의 작동과정을 알고싶다면 아래 링크 글을 참고하면 좋을 듯 하다.

https://jeong-pro.tistory.com/190

 

Protocol Buffer 원리로 배우는 고성능 직렬화, 역직렬화 전략! Protocol Buffer 예제 테스트(구글이 쓰는

프로토콜 버퍼가 무엇인가 프로토콜 버퍼(Protocol Buffer = protobuf)란 직렬화 데이터 구조다. (XML, JSON과 유사) 직렬화 데이터 구조를 알려면 직렬화(Serialization)가 뭔지 알아야한다. 꽤 긴데 천천히 설

jeong-pro.tistory.com

 

 

자바스크립트에서 protobuf 사용해보기

자바스크립트에서 protobuf를 사용하려면 우선 protobufjs 패키지를 설치해야합니다.

 

https://protobufjs.github.io/protobuf.js/

 

Index

Protocol Buffers are a language-neutral, platform-neutral, extensible way of serializing structured data for use in communications protocols, data storage, and more, originally designed at Google (see). protobuf.js is a pure JavaScript implementation with

protobufjs.github.io

 

아래 코드는 protobuf 방식으로 직렬화된 메세지를 만들고 해당 메세지, 인코딩된 메세지, 디코딩한 메세지를 출력해보는 코드입니다.

import protobuf from 'protobufjs';

protobuf.load("person.proto").then(root => {

  const Person = root.lookupType("Person"); 
  
  const message = Person.create({ name: "John Doe", id: 123, email: "johndoe@example.com" });
  const buffer = Person.encode(message).finish();
  const decodedMessage = Person.decode(buffer);

  console.log("Original message:", message);
  console.log("Encoded buffer:", buffer);
  console.log("Decoded message:", decodedMessage);

})

 


참고 자료

https://appmaster.io/ko/blog/peurotobeopeuran-mueosibnigga

https://velog.io/@chotony/%EC%A7%81%EB%A0%AC%ED%99%94Serialization%EC%99%80-%EC%97%AD%EC%A7%81%EB%A0%AC%ED%99%94Deserialization

https://martin.kleppmann.com/2012/12/05/schema-evolution-in-avro-protocol-buffers-thrift.html

https://jeong-pro.tistory.com/190

https://aq3aq4.github.io/back-end/protobuf/grpc/protobuf1/