게임을 개발하다보면 네트워크 관련 지식이 필요할 것이라 생각하여 게임 네트워킹에 대한 개념을 익히기로 했다. 나는 클라이언트 프로그래머이지만, 게임을 만들다보면 클라이언트와 서버를 연동하는 작업도 필요할 것이고, 협업을 조금 더 원활하게 하기 위해서는 네트워크 관련 지식도 필요할 것이라 생각한다.

 

관련해서 찾아보다가 유튜브에서 Tucker라는 분이 녹화하여 올리신 '게임 네트워킹의 이해' 라는 영상을 발견했는데, 크게 어렵지 않고 꽤나 흥미로운 내용들로 이루어져있다. 총 13개로 이루어져있고 현재까지 5개 정도 본 것 같다.

 

https://youtu.be/lAhAdnsIN6I

 

이전에 학교 다니면서 데이터통신, 컴퓨터네트워크 라는 과목을 배우기도 했었는데, 관련된 지식도 살짝살짝 나오긴 했지만 주로 새로 접한 내용들이 많았다.

 

아무튼, 영상을 보면서 접했던 내용들이나 생각했던 내용들에 대해서 정리해보고자 한다.

 

1. 네트워킹이란?

주로 컴퓨터끼리 데이터를 주고 받는 것을 네트워킹이라고 한다. 컴퓨터 내부에서 CPU<->RAM<->HDD 등 데이터를 주고 받는 것도 네트워킹이라고 하는데, 물리적인 거리가 가깝고 말 그대로 '연결'되어있기 때문에 일반적인 네트워킹과는 차이가 있다. 일반적인 네트워킹에서 크게 3가지 문제점이 발생하는데, 지연시간, 연결 안정성, 순서 비보장이다. 게임 네트워킹에서 이 3가지를 어떻게 처리하느냐가 중요한 이슈이다. (추후에 패킷 전송 비보장 얘기도 잠깐 나왔음)

 

먼저 지연시간은 빛의 물리적인 속도의 한계에 의해 생길 수 밖에 없다. 빛이 지구를 1바퀴 도는데 걸리는 시간이 대략 133ms이기 때문에, 지구 반대편에 있는 컴퓨터에 데이터를 전송하려면 아무리 빨라도 67ms가 걸린다. 특히나 게임의 경우, 데이터를 주고 받아야하기 때문에 이 시간의 2배까지 걸리게 된다. 이 왕복하는 시간 RTT(Round Trip Time)이라고 한다. 물론 실제로는 모든 컴퓨터들이 직접 연결된 것이 아니기 때문에, 도달하기 위해 여러 거점들을 거쳐야 하고, 일반적인 경우 지구 반대편이라면 500~600ms 정도가 걸린다고 한다.

 

두 번째로 연결 안정성에 대한 문제이다. 요즘에는 주로 생략해서 잘 쓰지 않는 것 같지만 www, world wide web이라는 표현이 있다. 이 이름처럼 인터넷 세상은 거미줄처럼 넓게 연결되어 있다. 때문에 내 컴퓨터나 상대방 컴퓨터에 문제가 없더라도, 데이터가 이동하는 사이 중간 거점에 문제가 생기면 연결에 문제가 생길 수 있다는 것이다. 한국에서 미국으로 데이터를 보낸다고 치면, 일본을 거쳐 태평양 회선을 타고 미국으로 도달한다고 하는데, 해저 케이블이 끊긴다거나 하는 사고가 발생하면 연결이 끊길 수 있다는 것이다. 이외에도 모바일 게임을 한다고 치면, 지하철을 타고 있을 때 중간중간 데이터가 잡히지 않는 구간이 있어서 끊김이 발생한다.

 

세 번째로는 순서 비보장이다. 광자가 순서대로 이동하기 때문에 컴퓨터 내부에서는 데이터가 순서대로 이동하겠지만, 인터넷 상에서는 순서가 보장되지 않는다. 두 명이 동시에 입력을 했다고 해도, 물리적인 거리가 멀다면 지연시간으로 인해 거리가 더 가까운 사람의 데이터가 먼저 도달할 것이다. 이렇게 물리적인 거리의 차이로 문제가 생길 수도 있고, 같은 사람이 보냈다고 하더라도 보내던 회선이 고장나서 다른 회선으로 우회하게 된다면 마찬가지로 나중에 보낸 데이터가 먼저 도달할 수도 있다.

 

===================================================

 

여기까지가 첫 번째 영상 관련 내용인데, 뒷 내용들에 비해서 내용이 조금 많은 것 같다. 전체적으로 어찌보면 상당히 당연한 내용이지만 여태까지 생각해본 적이 거의 없었던 내용들이었다. 먼저 지연시간과 관련해서 든 생각은, 두 플레이어 정 중앙에 서버가 존재한다면, 지연시간을 절반까지 낮출 수 있지 않을까 하는 생각이었다. 

그림을 그려보자면 이런 식인데, 중간에 서버가 양쪽의 데이터를 받아서 처리하고, 서로에게 보내준다면 데이터 왕복에 걸리는 시간을 절반까지 낮출 수 있을 것 같다. 다만 비용이 문제일 것 같다.

두 번째로 든 생각은 지구 내부에 구멍을 뚫어서 다이렉트로 연결하면 더 빠르게 연결할 수 있지 않을까 라는 생각이다. 지구 표면을 따라 이동한다면 반지름x3.14의 거리를 이동하겠지만, 이렇게 이동한다면 반지름x2의 거리를 이동할테니 1.5~1.6배 정도 빠르게 이동할 수 있을 것이다. 다만 아직 인간이 지표면에서 별로 깊이 들어가지도 못했고, 중심에는 핵이 있어서 케이블이 녹을 가능성이 매우 높다는 것이다. 아마 아직까지는 현실성 없는 얘기인 것 같다. ㅋㅋ.

 

=============================

 

2. TCP & UDP

 

TCP와 UDP는 각기 다른 통신 방식인데, 간단히 말하자면 TCP는 안정성을 중시하는 방식이고, UDP는 안정성을 포기하는 대신 속도를 중시하는 방식이다. 위에서 언급했듯 컴퓨터 네트워크에서는 연결 자체가 보장되지 않고, 순서도 보장되지 않으며 보낸 패킷들이 전부 도달한다는 보장도 없다. TCP방식은 이런 것들을 하드웨어 차원에서 보장해준다.

https://seongonion.tistory.com/74

먼저 연결의 경우 3-way-handshake라는 방식을 사용한다고 한다. 연결을 요청하면, 요청받은 쪽에서 응답하고, 이 응답을 잘 받았다는 것을 마지막으로 전달하면서 연결을 하는 방식인 것 같다. 이렇게 총 3번의 절차를 걸쳐 연결을 하기 때문에 3-way-handshake라고 하는 것 같다.

 

두 번째로는 순서 보장인데, 패킷을 보낼 때 번호를 매겨서 보내는 방식을 사용하여 받은 쪽에서는 해당 번호를 기준으로 정렬하면 되기 때문에 순서가 보장된다고 한다. 또, 3, 4, 5번 패킷이 왔는데 1, 2번 패킷이 안왔다면, 1, 2번 패킷을 못받았다는 요청을 보내서 모든 패킷을 전송받을 수 있는 보장도 가능하다는 것 같다.

 

 

다만, TCP 방식의 경우 이런식으로 확인에 대한 절차가 걸리기 떄문에 아무래도 성능적인 면에서 떨어질 수밖에 없다. 때문에 UDP 방식은 이런 보장을 해주지 않는 대신 속도가 빠르다는 장점이 있다. UDP는 연결 확인은 전혀 하지 않고, 바로 데이터를 보내고 '도달하든 말든 보냈으니 땡이다' 라는 방식인 것 같다. 상당히 무책임한 방식이지만... 복잡한 절차가 없으니 속도가 굉장히 빠를 것 같다. 데이터 유실률이 7%정도라고 하니 생각보다 그렇게 높지는 않은 것 같다. 때문에 반응성이 중요한 FPS나 격투 게임 등 대부분의 게임 장르에서는 UDP 방식을 사용한다고 한다. 요즘은 UDP방식을 소프트웨어적으로 보완한 Reliable UDP라는 방식을 사용한다고 한다. 게임에서 안정성이 필요한 부분의 안정성을 높여 순수 UDP에 비해서는 느리지만, 안정성은 좋은 방식이라고 한다. TCP 방식에 비해서는 불필요한 부분을 뺐을테니 TCP에 비하면 속도도 빠를 것이다. 옛날에는 이런 기술을 가진 회사들이 많지 않았다는 것 같은데, 지금은 오픈 소스도 많고 Unity, Unreal에서 지원해주기 때문에 많이들 사용한다고 한다.

 

 

3. Deterministic (+Delay, Rollback 방식)

 

게임 네트워킹 방식 중에 Deterministic이라는 방식이 있다. 이 방식은 반응성이 좋은 UDP를 사용하는 경우에 많이 사용한다고 한다. TCP를 사용하는 경우에는 부정을 방지하기 위해 서버의 강력한 권한이 필요한 MMORPG 등에서 Server Authority라는 방식을 사용한다고 한다.

 

Deterministic 방식은 똑같은 입력이 들어오면 똑같은 결과를 보장해준다. 만약 격투게임에서 원거리 통신 플레이를 할 때, 거리가 멀어서 지연시간이 길다고 가정해보자. 공격 버튼을 누른 후 적에게 공격이 닿을 때까지 100ms가 걸리는 경우, 지연시간이 150ms라면 무슨 일이 벌어질까? A가 100이라는 시간에 공격을 입력하고, B가 200이라는 시간에 공격을 입력하면 A에서는 200이라는 시간에 B를 때리는 결과가 나타날 것이고, B에서는 200이라는 시간에 B가 공격을 시작하고 A는 250에 입력이 들어와서 공격을 시작하기 때문에 결과적으로 300이라는 시간에 B가 A를 때리는 결과가 나타날 것이다. 온라인 게임에서 이렇게 두 플레이어의 결과가 다른 문제가 나타나면 안되기 때문에, 이를 해결하기 위한 방식을 적용한다.

 

첫 번째로는 Delay방식으로, 지연시간만큼 기다렸다가 입력을 처리하는 방식이다. 위의 경우를 똑같이 가정해보면 A의 입장에서는 100에서 입력을 했기 때문에 250에서를 처리를 할 것이다. 250까지 B의 입력이 오지 않았기 때문에 250에서 A의 공격이 나가고, 350에서 A가 B를 공격하는 결과가 나올 것이다. 마찬가지로 B의 입장에서는 200에 공격을 입력했고, 350까지 기다리는데, 250에 A의 공격 입력이 들어오기 때문에 마찬가지로 350에서 B가 A를 때리는 결과가 나타나게 된다. 즉, 두 플레이어에게 똑같은 결과를 보장해주는 것이다. 다만, 문제가 있다면 지연시간이 길 경우, 입력 후 실제 처리까지 대기시간이 있기 때문에 지연시간이 길수록 플레이어 입장에서는 답답하게 느껴질 수 있다.

 

두 번째로는 Rollback 방식인데, 위의 경우에서 B의 입장을 보겠다. B가 200에 공격을 시작하면 300에 A에게 공격이 도달할 것이다. 그런데, 250에 A의 입력이 들어왔을 때 A의 입력이 100에 입력됐다는 정보가 함께 오기 때문에, A가 정보를 보낸시간까지 되감기를 하고, 해당 정보를 넣은 후에 현재 시점까지 앞감기를 해서 적용을 시키는 방식이다. 그러면, A는 100에서 공격을 했기 때문에 200에 B가 맞은 판정이 날 것이다. 마찬가지로 A와 B가 동일한 결과를 보장받는 것이다. 다만, 이 경우의 문제는 B의 입장에서는 게임이 상당히 불합리하게 느껴질 수 있다는 것이다. B는 200에서 250까지 주먹을 날리고 있었는데, 되감기와 앞감기를 한 결과 200에서 공격을 맞게 되고, B가 보는 250의 순간에는 갑자기 주먹을 날리던 내 캐릭터가 적의 공격을 맞아서 날아가는 장면을 보게 될 것이다. 사실은 굉장히 공정한 처리가 이루어졌지만, 플레이어 입장에서는 전혀 공평하게 느껴지지 않을 것이다. 렉 때문에 죽었다고 생각하는 경우가 이런 경우라고 한다. 물론 이 예시가 지연시간이 굉장히 긴 경우를 예시로 들었기 때문에, 지연시간이 짧다면 이렇게까지 큰 차이는 나지 않을 것이고, Delay방식에 비해 훨씬 게임을 깔끔하게 진행시킬 수 있을 것이다.

단, Delay 방식에 비해서 구현하기가 굉장히 복잡하다는 문제가 있고, 중간 접속 처리를 하기가 까다롭다는 문제가 있다. 플레이어의 연결이 끊겼다가 다시 접속되는 경우, Delay방식에서는 게임이 잠시 중단될 것이다. 하지만 Rollback 방식에서는 접속한 플레이어가 이전까지의 다른 플레이어의 모든 입력을 가져와서 빠르게 앞감기를 하며 적용시켜야하기 때문에 중간 접속 처리가 굉장히 어려워지고, 이 과정에서 문제가 발생할 가능성도 높아진다.

 

다음으로는 실무에 많이 사용되는 방식에 대한 이야기인데, Delay 방식과 Rollback 방식과 비슷하지만 약간의 차이가 있다. 첫 번째는 중계 서버를 활용하는 방식이다. Relay Server 혹은 Broadcast Server라고 한다. 모든 입력을 서버를 거쳐서 처리하게 되는데, 서버는 데이터를 받아서 전달하기만 한다. 클라이언트는 입력을 할 때 서버에 데이터를 보내고, 서버에서는 받은 데이터를 일정 시간동안 취합하여 다시 클라이언트로 보낸다. 클라이언트는 서버에서 데이터를 받을 때 입력을 처리한다. 즉, Delay 방식과 거의 유사한 방식으로 보인다.

두 번째는 Rollback 방식에서 약간의 변화를 준 방식이다. 기존의 Rollback방식은 상대방의 입력이 들어오면 해당 입력이 입력된 시점으로 되감기를 하고, 다시 앞감기를 하는 처리를 거치는데, Rollback을 일정 시간마다 계속 반복하도록 하는 것이다. 입력이 들어올 때마다 특별한 동작을 수행하도록 하는 것이 아니라 항상 같은 동작을 수행하기 때문에 구현도 더욱 단순해지고, 문제가 생길 가능성도 낮아진다고 한다. 단점이 있다면 성능에 대한 문제인데, 매 프레임마다 되감기&앞감기를 하는 것이 성능에 큰 영향을 주지는 않는다고 한다. 게임에서 성능 대부분을 차지하는 부분이 그래픽이기 때문에, 되감기&앞감기를 하는 과정에서 화면을 다시 그리는 것이 아니라 연산만 하는 것이기 때문에 성능에 대한 부담은 거의 없다고 한다.

 

 

들은 내용의 기억을 되살려서 내 나름대로 요약을 해보았다. 누락된 부분도 있을 것이고, 왜곡되어 틀린 부분이 있을 수도 있다. 영상에서는 그림과 함께 실제 서버 프로그래머분이 설명을 해주시기 때문에 아마 영상을 보는 것이 더 좋을 것이다. 아무튼, 얕지만 게임 네트워킹에 대한 지식을 조금 알게 되었다. 앞으로 서버 관련 지식들을 익히는 데에 많은 도움이 될 것 같다. 현재 5번째 영상까지 보았는데, 총 13개로 이루어져있으니 더 많은 것들을 배울 수 있을 것 같다. 특히 MMORPG 서버 관련 내용이 기대된다.

+ Recent posts