공부/인프런 - Rookiss

Part 4-4-5. 패킷 직렬화 : Serialization #4

셩잇님 2023. 12. 7. 18:30
반응형

 

 

패킷 직렬화

 

 지난 시간에는 ushort, int 자료형과 같이 크기가 정해져 있는 자료형과는 다른 string 자료형의 패킷 Write, Read에 대해서 알아보았다. 이는 크게 2가지의 방법으로 나뉘어져 있는데, 먼저 String Packet의 사이즈를 확인하고 그 다음 내부 데이터 값을 전송하는 방법이었다.

 

 그렇다면 오늘은 String에서 더 나아가 List 자료구조를 보낼 때에는 어떻게 처리해야 하는지에 대해서 학습해본다.

 


 

 

💷 List Packet 

 그렇다면 List Packet은 어떻게 넘겨줄 수 있을까? 예시를 들어 설명하기 위해 기존에 작업하던 PlayerInfoReq 클래스에 새로운 List를 추가하자.

 

public List<SkillInfo> skills = new List<SkillInfo>();
{

}

public struct SkillInfo
{
    int id;
    short level;
    float duration;
}

 

 그냥 List에 int, double과 같은 자료형을 넣어서 사용한다면 String과 별반 다를 것이 없기 때문에 구조체(Struct)를 만들어 List를 만들고, SkillInfo 구조체 안에는 스킬의 Id, Level, Duration에 관한 정보를 담아준다.

 

🧻 SkillInfo 클래스 내 Write

 

 

 SkileInfo 클래스 내부에 Wirte라는 함수를 새롭게 만들어 준다. 여태까지 Span을 이용하여 작업하였기 때문에 Span을 받아 처리하며, ref 키워드를 이용해 count를 받아 각 스킬의 Id, Level, Duration을 각자의 타입으로 받아와 넘겨준다. 혹시 모르는 bool 변수를 두어 해당 값을 이용해 에러를 방지하여 준다.

 

🩳 PlayerInfoReq 클래스 내 Write

 

 

 

 PlayerInfoReq Wirte 메서드 내부로 이동하여 기존에 작업하돈 곳 하단에 새롭게 skills.Count를 받아와 미리 List의 크기를 넣어서 할당해주고, 스킬이 여러개일 수 있으므로 foreach문을 통해 List를 순회하며 인코딩 작업을 진행한다.

 

skills.count를 그냥 넣어주게 될 경우 int 타입으기에 4바이트가 들어가게 된다. 반드시 앞에 ushort를 추가하여 캐스팅을 해주자.

 

 

🧻  SkillInfo 클래스 내 Read

 

 

 SkillInfo 내 Read 메서드를 Write 메서드와 같이 새롭게 만들어준다. 기존 PlayerInfoReq 클래스 내부에서 사용했던 ReadOnlySpan 및 count를 받아와 SkillInfo의 Id, Level, Duration을 읽어서 확인한다.

 

float 자료형은 변환할 대에 BitConverter.ToSing 키워드를 이용하여 처리한다.

 

 

🩳 PlayerInfoReq 클래스 내 Read

 

 

 PlayerInfoReq 클래스로 다시 돌아와 먼저 List의 크기를 받고, count의 사이즈 만큼 올려준 뒤 역시 for문을 순회하며 skill을 담아준다.

 

왜 Read인데, Add를 해줘야 할까?
메시지를 읽는 서버 쪽에서는 구조체에 담긴 데이터가 없기 때문에 Add를 통해서 데이터가 들어왔는지 알 수 있기 때문에 Add를 해줘야 한다.

 

 


 

 

실행 결과 😎

 패킷을 전송할 때에는 기존 스킬 말고 새로운 스킬도 다양하게 추가하여 넣어준다.

 

 

 마찬가지로 전송받은 패킷을 읽어오는 쪽에서도 아래 이미지와 같ㅇ foreach문을 통해 이를 받는다면 

 

 

 정상적으로 실행되는 것을 볼 수 있다. 👍

 

 


 

P.S

일반적으로 Serialization 할 떄에 자주 사용되는 라이브러리 2가지가 있다. 바로 프로토 버퍼와 플랫 버퍼이다. 

 

프로토 버퍼
구글에서 제작한 방법. 우리가 작업했던 것과 같이 List에 Add로 skill의 정보를 넣는 방식이다. 즉 중간에 인스턴스하여 넣는 방식. 이는 성능 상에 손해는 발생하겠지만 보다 직관적이고 관리하기 편하기에, 약간의 손해를 감수하더라도 사용할만하다.

 

플랫 버퍼
배열에 담아 한 번에 전송하는 방식으로 가독성은 좋아지지만 어떤 부분에 어떠한 문제가 생긴 것인지 프로토 버퍼에 비해 직관적으로 파악하기가 어렵다.

 

 

 

반응형