ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스파르타) The Last Rollback (D-33, Node.js 게임 서버 최종 프로젝트)
    TIL 2024. 7. 25. 21:49


     > 과제 진행 간 완료한 사항 및 문제점과 해결 과정을 정리해보았다.


    학습 키워드:
     Protobuf, C#

     

    1. 과제 진행 간 알게된 것

    1) 프로토콜 버퍼 관련 사항:

     바로 어제자 TIL의 2. 문제점 1) 에서 작성한 내용인데, 어제는 원인이 명확하지 않아서 두 번 직렬화 하고 역직렬화 하는 과정에서 문제가 생긴다고 판단했으나, 팀원과 상의해본 결과 역직렬화 로직 자체에서는 태그를 잘 못 인식할 가능성이 없다고 결론이 내려졌다. 이상하다고 생각되어 어제와 동일한 구조를 만든 뒤 테스트 해보니 실제로 다시 역직렬화가 잘 되는 것을 확인했다. 분명 ResponsePacket 구조도 전부 일치했고 서버측 직렬화 및 역직렬화가 정상적으로 동작하는 것을 console로 찍어서 확인 했고, 매핑된 패킷 번호 또한 변동이 없었으며 어제 작성한 대로 바이트 배열까지 동일했는데 대체 어느 부분에서 문제가 발생한 것인지 알 수가 없게 되었다. 아무튼 핵심만 말하자면 어제 결론 내린 것과 다르게 패킷 구조를 protobuf로 encode한 buffer를 다른 메세지의 bytes 타입 필드에 넣고 또 한 번 직렬화하는 구조에는 문제가 없는 것으로 판명났다.

     

    message RequestPacket {
      string clientVersion = 1;
      uint32 sequence = 2;
      string token = 3;
      uint32 payloadType = 4;
      oneof payload {
        C_Enter cEnter = 5;
        C_Move cMove = 6;
        C_Animation cAnimation = 7;
        C_Chat cChat = 8;
        C_EnterDungeon cEnterDungeon = 9;
        C_PlayerResponse cPlayerResponse = 10;
        C_SignUp cSignUp = 11;
        C_LogIn cLogIn = 12;
      }
    }

     

     또한, 이전 프로젝트를 진행하면서 위와 같은 구조에서 우측 숫자가 항상 1 부터 시작하고 순차적으로 늘려나가야 하는 것으로 알고 있었는데, 실제로는 동일한 숫자를 사용하지만 않는다면 어느 숫자를 어느 위치에 넣든 아무런 문제가 없다. 단, 송수신 측 모두가 동일한 넘버를 가지고 있어야 한다는 제약이 있다.

     

     

    2) C# property 이름을 string 값을 통해 설정하기:

    public void Send(IMessage payload) {
        // determine payload type
        Type t = payload.GetType();
        string msgName = t.Name.Replace("_", String.Empty);
        MsgId msgId = (MsgId)Enum.Parse(typeof(MsgId), msgName);
    
        // wrap in reqPkt
        RequestPacket reqPkt = new RequestPacket {
            ClientVersion = "1.0.0", // 임시
            Sequence = 1, // 임시
            Token = "token1", // 임시
            PayloadType = (ushort) msgId,
        };
    
        PropertyInfo propInfo = reqPkt.GetType().GetProperty(msgName);
        propInfo.SetValue(reqPkt, payload);
    
        _session.Send(reqPkt);
    }

     C#에서 string의 값과 동일한 이름의 property를 찾고 그 값을 설정하는 방법을 알아보았다. 먼저 property를 찾을 class의 타입을 인스턴스의 GetType() method를 통해 알아낸 뒤, 해당 타입 객체에서 다시 GetProperty() method에 인자로 찾고있는 프로퍼티의 이름을 string 값으로 넘겨줘서 PropertyInfo 인스턴스를 얻어낸다. 마지막으로 획득한 PropertyInfo 클래스의 인스턴스에서 SetValue() method를 호출하면 되는데, 첫 번째 인자로 해당 프로퍼티가 있는 인스턴스를, 두 번째 인자로 해당 property에 설정할 value를 넘겨주면 끝이다. 위 코드는 해당 방식을 이용하여 reqPkt의 oneof로 설정되어있는 payload가 되는 메세지 타입들의 이름을 찾아서 넘겨받은 payload 값을 지정해주는 용도로 사용되는 함수다. 

     

     

    3) Redis 관련 알게된 점 (짧):

     팀원들과 회의 중 알게된 사실인데, redis 및 ioredis 라이브러리에서는 자체적으로 sequence가 관리되어서 set 함수와 get 함수를 연달아 호출할 때 내부 command queue에서 작업 전송 순서를 보장한다고 한다. 단, 네트워크 상태에 따라 redis 서버에 도착할 때 전송 순서와 다른 순서일 가능성이 있으므로 실제 순서를 보장하려면 set, get 등의 명령어를 실행할 때 await을 붙여야 한다.

     

     

    --


    REFERENCES:

     

     

    GitHub - eliotjang/the-last-rollback-server: 액션 MORPG

    액션 MORPG. Contribute to eliotjang/the-last-rollback-server development by creating an account on GitHub.

    github.com

     > 프로젝트 repo

     

    728x90
Designed by Tistory.