스파르타) The Last Rollback (D-32, Node.js 게임 서버 최종 프로젝트)
> 과제 진행 간 완료한 사항 및 문제점과 해결 과정을 정리해보았다.
학습 키워드: Protobuf, Node.js, C#, Unity, TCP, serialize, deserialize, enum
1. 완료한 과제 진행 사항
1) ~기능 구현 완료:
35 update 통지 패킷 구조 추가 by donkim1212 · Pull Request #36 · eliotjang/the-last-rollback-server
관련 Issue close #35 작업 내용 #35 에서 명시한 작업 완료 주요 변경 사항 클라이언트의 핸들러가 받는 두 번째 인자를 IMessage 타입으로 원상 복구 변경 전: 변경 후: sendNotification 기능 활성화
github.com
- Notification 패킷 구조 추가 및 패킷 송수신 구조 수정
- 기존 구조에서는 클라이언트가 RequestPacket을, 서버가 ResponsePacket 만을 보내고 있었는데, 초반에는 다른 패킷 타입의 추가를 고려하지 않고 설계해서 핸들러의 인자를 IMessage 타입에서 ResponsePacket 타입으로 바꿔두는 등 이것저것 바꿔둔 부분이 많았으나, 회의를 통해 최종적으로 바깥 패킷 (oneof payload를 가지는) 구조를 추가하는 것으로 결론이 나서 코드 작성에 혼선이 없도록 구조를 다시 원래의 형태로 수정하게 되었다.
- Notification 패킷 구조를 추가하면서 Response 패킷 구조와 동일한 payload를 쓰게되는 상황이 있는지 토의해본 결과 몇몇 payload message 구조는 통지와 응답 패킷에 똑같이 사용될 수 있는 것으로 결론이 나서 이를 같은 핸들러에서 처리할 수 있도록 외부 패킷 (Response | Notification)을 우선적으로 역직렬화 하고, 응답 패킷의 경우 에러 코드와 메세지를 따로 받아서 처리할 수 있는 PacketErrorCodeHandler 클래스를 생성하게 되었다.
- 그 외 상세 내용은 위 PR 및 연결된 Issue 참고
2. 과제 진행 간 문제점
1) Protobuf로 직렬화된 key의 값이 undefined인 문제 (해결):
// 클라이언트의 패킷 전송 코드
...
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);
}
...
Protobuf 패킷 전송 구조를 손보는 도중 특정 패킷 전송 시 payloadType 값이 undefined가 되는 문제가 있었다. PayloadType 값을 컴파일된 protobuf 파일의 enum 값으로 얻어오고 있었기 때문에 잘 못된 값을 넣어줄 수가 없는 구조여서 문제가 무엇인지 검색하면서 StackOverflow의 어느 글을 통해 원인을 바로 알게 되었다. 아래는 해당 글의 답변이 참조한 공식 문서 내용이다.
공식 문서에서 정의하기를, enum 의 기본값은 0인데, scalar 값이 encode된 후에는 이 값이 기본 값인지 직접 지정한 0 값인지를 알 수 없고, 기본 값으로 지정된 scalar 메세지는 wire에 직렬화되지 않는다고 한다. 이러한 특징으로 인해 공식 문서의 예시에서는 0 번째 매핑을 UNSPECIFIED로 사용하고 있다.
우선은 서버에서 undefined payloadType을 받게 되면 0으로 치환해주도록 수정했으나, 추후 패킷 매핑 번호를 손보게되면 0번을 제외하도록 해야겠다.
3. 기타 사항
1) Unity에서의 JWT 토큰 저장? (짧):
서버에서 전송해주고 있는 토큰을 클라이언트에서 어디에 저장하고 어떻게 보내줄 지?
찾아보기:
- PlayerPref, Unity Authentication
--
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
Language Guide (proto 3)
Covers how to use the version 3 of Protocol Buffers in your project.
protobuf.dev
> Protobuf 공식 문서 (Figure 2)