[C#, 게임서버] Protobuf란?

Arthur·2023년 7월 18일
0
post-thumbnail

Protobuf는 다양한 분야에서 사용된다는 것을 알게 되었습니다.
처음에는 게임 개발 쪽에서 주로 사용되는 것인줄 알았습니다.
구글링을 하면서 찾아보니까 텐서플로우에서도 사용된다고 합니다.

이런 Protobuf를 좀더 자세히 알기 위해,
C# 게임 서버를 기준으로 작성해보기로 했습니다.

❗이 글은 Protobuf3을 기준으로 작성했습니다❗

Protobuf란?


프로토콜 버퍼(Protocol Buffers, Protobuf)는 구조화된 데이터를 직렬화하는 방식이다.
유선이나 데이터 저장을 목적으로 서로 통신할 프로그램을 개발할 때 유용하다.
<위키백과, wikipedia>

Proto file(.proto) 형식의 파일에 언어에 맞게 양식을 작성하면
컴파일을 통해 각 언에 맞는 소스 파일이 생성됩니다.
Protobuf Documentation을 접속(영문 사이트)하면 예제와 설명을 볼 수 있습니다. => 링크

예시 코드

syntax = "proto3";
package tutorial;

import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Protobuf.Examples.AddressBook";

message Person {
  string name = 1;
  int32 id = 2;  // Unique ID number for this person.
  string email = 3;

  enum PhoneType {
    PHONE_TYPE_UNSPECIFIED = 0;
    PHONE_TYPE_MOBILE = 1;
    PHONE_TYPE_HOME = 2;
    PHONE_TYPE_WORK = 3;
  }

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;

  google.protobuf.Timestamp last_updated = 5;
}

// Our address book file is just one of these.
message AddressBook {
  repeated Person people = 1;
}

message는 클래스와 같은 형태를 가지고 있고 Enum도 있습니다.
자료형은 string, int32와 같은 형태로 나오는데 C#에 해당하는 자료형은 아래의 표와 같습니다.


.proto TypeC# Type
doubledouble
floatfloat
int32int
int64long
uint32uint
uint64ulong
sint32int
sint64long
fixed32uint
fixed64ulong
sfixed64int
sfixed64long
boolbool
stringstring
bytesbyteString

메시지 필드에 위와 같은 타입들을 작성해서 사용 할 수 있습니다.

자세한 내용은 Protobuf Docs(링크)에서 확인 하실 수 있습니다.



Protobuf를 사용하는 이유


  • 하나의 언어에 종속적이지 않고 다양한 언어 지원
  • 다른 포맷(JSON, XML) 보다 직렬화/역직렬화 속도가 빠르고 크기가 작다

프로토콜 버퍼는 proto file이라는 형태로 저장합니다.
Protobuf는 어느 하나의 언어에 종속 되는 것이 아닌 다양한 언어를 지원합니다.
(C++, C#, Go, Java, Python, Object C, JavaScript, Ruby등을 지원)

게임 서버를 C#으로 구현해도 Protobuf를 사용해 데이터 직렬화를 한다면,
클라이언트가 언리얼이던 유니티이던 둘 다 지원이 가능하다고 합니다.

이렇듯 한번 정의해놓으면 변경에도 유연한 것을 알 수 있습니다.

이 외에도 직렬화 속도가 빠르고 파일의 크기도 작아서 다양한 분야에서 사용된다고 합니다.

속도가 빠르다는 것이 너무 추상적으로 다가올 수 있습니다.
JSON, XML 포맷과 비교를 하면 이런 차이점을 좀 더 확연하게 느낄 수 있습니다.



Protobuf와 XML, JSON과의 차이점


구조화된 데이터는 바이너리 형식으로 저장되기 때문에 XML, JSON 형식과 같은 텍스트 기반 형식보다 훨씬 작아 네트워크를 통한 전송이 더 빠릅니다.

Protobuf는 바이너리를 형식을 사용해서 직렬화/역직렬화에 큰 이점을 얻습니다.
반대로 XML, JSON 형식은 텍스트 기반이기 때문에 따로 파싱을 해줘야 하는 라이브러리가 필요합니다.
(자바, C#과 같은 언어에서는 JSON 파싱 내장 함수가 구현되어 있습니다.)

웹 개발에서 Spring 프레임워크를 보면 Jackson 이라는 라이브러리가 JSON 파싱을 담당합니다.

XML, JSON 예시

// XML
<friend>

       <name>Charlie</name>

       <name>Steve</name>

</friend>

// JSON
{
	"friend": [
    {
    	"name": "Charlie"
    }
    {
    
    }
    	"name": "Steve"
    ]
    
}

예시를 보면 알 수 있듯이 형식에도 큰 차이를 보입니다.
하지만 XML과 JSON은 텍스트로 이루어져 있기 때문에 가독성이 좋습니다.

차이점을 정리하면 아래와 같습니다.

  • Protobuf는 바이너리 형식이고 XML, JSON은 텍스트 기반 형식이다.
  • Protobuf는 효율적인 바이너리 직렬화를 제공해 크기가 작고 직렬화/역직렬화 속도가 빠르다.
  • XML, JSON은 텍스트 기반이라 좋다.
  • XML, JSON은 텍스트 기반이라 별도의 파싱 기능이 필요하다.

❓그러면 게임 서버에서는 JSON을 사용 안할까?

JSON과 같은 텍스트 형식의 포맷을 사용하는 것은 게임의 장르와 활용 용도에 따라 다릅니다.


실시간 동기화의 비중이 높은 멀티플레이 게임은 성능이 상당히 중요합니다.
예를 들면 멀티 플레이 FPS게임이 그렇습니다.

FPS는 유저가 입력한 수 많은 이벤트를 패킷을 서버에 전송합니다.
그리고 캐릭터의 위치가 바뀌면 해당 위치에 대한 값도 동기화를 해줘야 합니다.

이런 게임의 장르에서는 JSON 포맷을 사용한다면 동기화가 지연되는 문제가 발생할 수 있을 것입니다.

하지만 실시간 동기화의 비중이 낮은 게임은 JSON과 같은 형식을 사용 한다고 합니다.


(Protobuf의 원리와 성능에 대한 것은 이 블로그링크에 들어가 보시는 것을 추천드립니다.)



참고 자료


  • Protobuf란 무엇인가요? => 링크
  • Protocol Buffer Basics: C# => 링크
  • 위키백과 - 프로토콜 버퍼 => 링크
  • 구글 프로토콜 버퍼 (Protocol buffer) => 링크
profile
기술에 대한 고민과 배운 것을 회고하는 게임 서버 개발자의 블로그입니다.

0개의 댓글