지난주에 책을 읽으며 깨달은 사실

7.4 신뢰성: TCP냐 UDP냐

TCP의 신뢰성, 흐름제어 및 혼잡제어는 아주 강력하다. 반드시 패킷을 손실 없이, 순서대로 수신하도록 해준다.

그러한 강력한 점 때문에 게임에선 아쉬울 수 있는 상황이 있다. 실시간의 네트워크 상황에 의해 다음 패킷이 먼저 도착했더라도 먼저 처리할 수 없다. 이전 패킷이 도착해야만 순서대로 다음 계층으로 패킷을 전달해주기 때문이다. 그래서 통신할 때 데이터의 신속성이 무엇보다도 중요하다면 위의 장점을 포기하고서라도 UDP로 구축할 수 있다.

예를 들어 위치 정보는 과거 정보보다 더 현재 시간에 가까운 나중에 들어온 정보가 이미 있다면 그대로 처리해줘도 무방하다.

또한 만약 송신측에서 발송한 패킷이 유실되었을 때, 몇 개쯤 유실되어도 괜찮아서 다시 보내고 싶지 않을 때에도 UDP가 적절하다.

현재 프로젝트는 TCP로만 구축돼 있다. 그런데 배드민턴을 쳐야 하는 게임 특성상 위치 정보의 신뢰성이 중요하므로, TCP의 지연이 불편하게 작용할 수 있을 것 같다.

UDP 위에서 동작하도록 구현을 변경해보자.

궁금한 사항. UDP 위에서 신뢰성 매커니즘을 구현한다면, 패킷이 유실되거나 순서가 잘못 도착하는 것에 대한 처리는 가능할 것 같다. 그런데 네트워크의 흐름을 제어해야 하는 흐름 제어, 혼잡 제어에 대해서는 어떻게 대응할 것인가? UDP이니 막 보내기? 배달 통지 매커니즘이 있으면 매번 RTT를 측정하면서 PP 값을 결정할 수 있겠다. 이렇게 동적으로 PP를 결정하면 곧 흐름 제어가 될 수 있을 것 같다.

지금 무엇을 진행하는가?

어쨌든 TCP든 UDP든 NetworkManager 하위에서 벌어지는 일이니, 패킷을 전달 받았다고 가정하고 상위의 기능을 개발해도 문제 없겠다. 지난주 목표였던 Replication Create/Update 동작을 우선 마저 완성하자!

Unity에서 PacketType, ReplicationAction을 받아 처리하도록 넘겨주는 코드를 만들었다.

테스트 해보고자 서버를 돌리니, 서버가 터진다!!!! 어디서 터지는거지!!

디버깅 결과 ReplicationUpdate로 전달되는 shared_ptr<gameObject> 객체가 nullptr 전달 된다. 분명 networkId는 1로 시작하는데, get의 결과로 얻은 networkId는 0이었다. 여기부터 문제가 있다.

gameObject에 networkId를 저장하지 않는 문제점을 찾았다. linkingContext가 자체적으로 gameObject별 networkId를 갖고 있으므로, gameObject는 networkId 필드를 갖지 않기로 했다.