protobuf는 어떻게 사용해요?

방구석 호랑이·2022년 9월 20일
0
post-thumbnail

protobuf

소개

프로토콜버프(Protocol Buffers) 혹은 프로토버프(protobuf)라고 불리는 이것은 구글에서 개발하고 오픈소스로 공개한 직렬화 데이터 구조(serializing data structure)이다. 쉽게 말해서 이미 xml과 json와 같은 데이터 전송 방식과 같다고 생각하면 된다. 물론 xml과 json은 객체 직렬화 방식이다.

protobuf는 언어 및 플랫폼 중립적이고 확장성이 좋다는 특징을 가지고 있는데, XML과 유사하지만 더 작고 빠르며, 포맷을 정의하기만 하면 컴파일을 통해서 C++ / C# / Java / Python / Go / Ruby 등의 언어에 대해서 바로 코드형태로 바꿀 수 있다.

json vs xml vs protobuf

JSON

  • 인간이 읽고 쓸 수 있다. : 개발과 디버깅이 편하다.
  • 스키마에 대한 정보 없이, 사용할 수 있다.
  • 웹 브라우저에서 사용하기 좋다.
  • XML에 비해서 가볍다.
  • 딱히 표준이라 할 만한 것들이 없다.

XML

  • 인간이 읽고 쓸 수 있다. : JSON 보다는 복잡하긴 하지만..
  • 스키마에 대한 정보 없이, 사용할 수 있다.
  • SOAP등의 표준이 있다.
  • xsd, xslt, sax, dom 과 같은 좋은 툴들이 많다.
  • JSON에 비해서 좀 장황하다.

protobuf

  • 데이터 압축률이 좋다.
  • 정보를 얻기 위해서는 스키마에 대한 정확한 지식이 필요하다.
  • 처리속도가 빠르다.
  • 이진 데이터라서 사람의 눈으로 확인할 수 없다.

원리

우선 우리가 데이터를 수신하는 방법을 생각해보자, 아래에는 Person 클래스를 json으로 포멧한다면 이런식으로 만들어 질 것이다.

이 json의 크기는 공백을 제외하고 총 82byte를 사용했다.(string으로만 따졌을 때)

그렇다면 protobuf를 사용하면 어떻게 될까? Person 클래스를 protobuf로 스키마를 만든다면 이렇게 될것이다.

그리고 이 스키마를 이용해서 인코딩하여 크기를 계산해 보면 아래와 같이 계산이 될 것이다.

어떻게 이런게 가능할까?

protobuf에서는 불필요한 속성값(user_name, interests)은 숫자로 대체해버리고, 1번이라는 값에 매칭을 해서 값을 가지고 오는 형식으로 데이터를 표현하게 된다.

gRPC

gRPC는 언어에 제약 받지 않는 고성능 RPC(원격 프로시저 호출) 프레임워크이다. 서버와 클라이언트는 protobuf 스키마를 가지고 통신을 할 수 있으며, 속도가 매우 빠르다.

RPC가 뭐야?

RPC(Remote Procedure call)이란, 별도의 원격 제어를 위한 코딩 없이 다른 주소 공간에서 리모트의 함수나 프로시저를 실행 할 수 있게 해주는 프로세스간 통신입니다. 즉, 위치에 상관없이 RPC를 통해 개발자는 위치에 상관없이 원하는 함수를 사용할 수 있습니다.

  • Caller / Callee
    • 사용자(Client / Server)가 필요한 비즈니스 로직을 작성하는 Layer
    • IDL(interface definition language)로 작성
  • Stub
    • Stub Compiler가 IDL 파일을 읽어 원하는 Language로 생성.
    • Parameter Object를 Message로 marshalling/unmarshalling하는 Layer
  • RPC RunTime
    • Server와 Client를 Binding하는 Layer
    • 커뮤니케이션 중 발생한 에러 처리도 진행

장점

  • 고유 프로세스 개발 집중 가능 (하부 네트워크 프로토콜에 신경쓰지 않아도 되기 때문)
    • 클라이언트는 함수만 알아도 개발을 할 수 있다.
  • 프로세스간 통신 기능을 비교적 쉽게 구현하고 정교한 제어가 가능
    • 스키마 퍼스트(데이터 퍼스트) 개발을 하기 때문에, 클라이언트와 서버끼리의 소통비용을 감소 시킬 수 있다.

단점

  • 호출 실행과 반환 시간이 보장되지 않음 (네트워크 구간을 통하여 RPC 통신을 하는 경우, 네트워크가 끊겼을 때 치명적 문제 발생)

사실 문제가 있어요...

사실 위에서 언급하지 않았지만, protobuf에서는 javascript에 대한 지원을 해주지 않고 있다. (그러면서 왜 gRPC에서는 node를 지원할까...)

그래서 이것을 해결하기 위해서 오픈소스로 pbjs라는 것을 만들었지만, Typescript에 대한 지원이 부족하고 타입이 일치하지 않는 버그가 종종 발생한다.
https://github.com/evanw/pbjs

그래서 Riiid에서는 이러한 점을 해결하기 위해 pbkit이라는 툴을 만들고, 오픈소스로 공개하고 있다. pollapo라는 스키마 매니저를 사용하여, 레파지토리에서 protobuf 스키마를 가져오고 pb를 통해 code-gen을 하여 사용하고 있다.
https://github.com/pbkit/pbkit

보너스

gRPC&GraphQL

GraphQL

기존의 REST API의 경우, 정의된 요청에 대한 응답만 가능했다면,

GQL은 필요한 컬럼에 대해서만 선택적으로 요청할수 있어 불필요한 데이터를 받지 않고, 필요한 데이터만 받을 수 있습니다.

gRPC

gRPC는 클라이언트의 요청으로 서버의 정의되어있는 함수를 수행시켜 단순히 데이터만 주고받는게 아닌,

클라이언트가 서버에게 원하는 일들을 훨씬 폭넓고 다양하게 시킬수가 있습니다.

참조

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

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

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

https://www.joinc.co.kr/w/man/12/ProtocolBuffer

profile
재미있는 세상을 위해 개발합니다.

0개의 댓글