게임 서버 동기화 - geim seobeo dong-gihwa

안녕하세요 대학생개발자입니다.

이번 글에서는 여러가지가 짬뽕이 될 것같은데요... 사실 이걸 c,c++로 넣어야될지 아니면 게임서버쪽으로 봐야될지 고민을 하다가 그냥... 이것만을 위해서 새로운 카테고리를 파기는 좀 그래서 그냥 c,c++로 넣어버렸습니다.

일단 시작하겠습니다.

음... 어떻게 시작해야될지를 모르겠습니다.

사실 이부분을 필기한지가 꽤나 시간이 지나서 무슨 말을 했었던건지도 기억이안나고... 필기도 너무 빠르게 해서 그런지 핵심내용이 많이 사라져있네요...

일단 서버의 경우에는... 대체적으로 하드웨어를 분산시키는 기법을 많이 사용하죠. 말그대로 분산서버인데요.

아마 구글링을 해보신 분들은 다 아시겠지만 뭐 채팅서버, 로그인서버, 로비서버, 게임서버, 월드서버, NPC서버 등등 다양한 서버들이 존재합니다.

하지만 최근에는... 코어의 갯수가 말도안되게 많아지고있고 심지어 속도도 빨라졌기때문에 스레드 조율을 잘해서 그냥 하나의 서버에서 모든걸 처리하고 서버군을 여러개 두는 식으로 가는 방법을 많이 채택하는데요.

네트워크를 통해서 다른 컴퓨터 까지 갔다가 거기서 로직을 처리하고 다시 네트워크를 타고 돌아오는 시간이면 사실... 요새 컴퓨터에서는 충분히 로직을 돌리고나서 돌려주는게 더 빨라질수 있거든요.

예를 들어서 AI서버가 있다고 가정을 해보겠습니다. AI로직이 매우 복잡하다면 사실 따로 구분짓는것도 나쁘진 않은 선택입니다.

하지만 AI가 만약 그저 길찾기 알고리즘 하나만 가지고있다고 한다면...

게임서버에서 AI()라는 함수를 호출했을때 일어나는일은

1. (게임서버에서)msg생성.

2. (게임서버에서)send().

3. (AI서버에서)recv().

4. (AI서버에서)분석

5. (AI서버에서)처리

6. (AI서버에서) 결과 msg생성

7. (AI서버에서) send().

8. (게임서버에서) recv().

9. (게임서버에서) 분석

10. (게임서버에서) AI에 대한 결과 도출;

이런 로직을 거쳐야되는데 물론... 이것도 사람이 느끼지는 못할 속도입니다. 하지만... 로컬안에서 메모리 복사가 일어나는 것이랑은 차원이 다르겠죠.

분명 게임서버가 분산이 되었을때 생기는 이득보다 분산이 안된 경우에 이득이 더 커지게 되는 경우가 존재하게 될겁니다. 가령 채팅서버를 분산을 했다고 가정하면... 채팅은 온 패킷을 그냥 같은 방에있거나 같은 채널에있거나 같은 서버에있는 사람에게 그냥 다 뿌리는 역할만을 할겁니다. 근데 이런 기능을 굳이 다른 하드웨어를 통해 돌린다..? 이건 진짜 오히려 더 늦어질거 같군요...

하지만 아직도 서버를 분리를 해서 쓰는 곳이 있다고 한다면 제가 추측하기에는 2가지의 케이스가 있을 것 같습니다.

1. 서버를 합치려고 했지만 못했다.

2. 만약 A라는 기능에 문제가 생겼으면 A서버만 죽으면 되지만 만약 통합이 되어있다면 그냥 서버전체가 죽어버리게 될 수 도있다.

이 두가지 케이스일 것 같군요... 뭐 여기는 사실 제 주관의 부분이라 누군가 들었을땐 일리있다고 생각하겠지만 누군가 들었을땐 뭔 개소ㄹ 하고있냐하고 볼수도있습니다... 하지만 어디까지나 이건 제 생각이고 아직 배우는 중이기 때문에 잘 모르니까 이런거라고 생각해주셨으면 좋겠습니다.

물론 서버의 경우에는 절대 안죽게 만드는게 제일 최우선이겠지만요...

음... 일단은 동기화에 대한 얘기를 조금 해봐야겠습니다... 이 케이스는 서버내부에서 쓰레드동기화와 같은 문제가 아니라 클라이언트와 클라이언트간에 동기화를 의미합니다.

사실 한국 내부에서 환경이라고 한다면 네트워크에는 레이턴시라는게 거의 존재하지 않죠 길어봐야 3ms정도 나올겁니다. 하지만 우린 분명 레이턴시가 10미리세컨드 단위라는걸 게임을 하다보면 확인할 수 있는데요... 원인이 무엇일까입니다. 사실 일반적으로 알려진 레이턴시라는건 RTT인데요... 클라이언트가 send한 순간부터 서버에 도착해서 서버의 로직을 거치고 다시 클라이언트로 도착해서 보여지기 까지의 시간이죠. 대부분 이 케이스를 레이턴시라고 부르더라구요. 사실 네트워크의 레이턴시는 국내 환경에서는 거의 없다고 보시는게 맞을 것 같아요.

그냥... L7의 로직처리 시간이 길어서 네트워크 지연처럼 느껴지는거란 겁니다.

그럼 클라이언트의 동기화를 잘 맞추려면 어떤 방식으로 해야될까입니다.

사실 이부분은 너무 당연한 말이지만 서버에서 거의 모든 데이터의 처리를 하고 일괄적으로 뿌려버리면 사실 동기화가 제일 잘 맞습니다. 그리고 서버에서 일어나지 않은일은 없었던 일이 되기 때문에 억울한 경우도 안생기죠.

즉 서버가 주도적으로 처리를 해서 클라이언트에게 전달을 해야되고 그걸 클라이언트가 받아서 처리해야되는겁니다.

하지만 우리는 게임을하다보면 일반적으로 레이턴시가 10이상 떠있는걸로 확인이 되는데요... 그러면 우리가 누른다음에 쪼금있다가 반응하기때문에 반응성이 떨어지는 것 아니냐 라는겁니다.

이부분에 대해서는 사실 클라이언트에서 해결을 해줘야합니다. 뭐 마우스클릭으로 이동을 한다고 하면 이동을했을때 이동 지점의 땅에 표식이 생긴다던지... 아니면 이펙트가 터진다던지 이런 효과들을 이용해서 내가 누르자 말자 반응하는것 처럼 보이게 하는거죠.

흠... 그럼 마우스의 경우에는 오케이... 좋습니다 내가 누른곳에 이펙트가 터진다고 해보겠습니다. 그럼 키보드 입력으로 움직이는 경우에는요??

키보드의 경우에는 도착지에 대한 정보가 없기때문에 따로 도착지에 이펙트를 미리 띄워놓을 수도없습니다.

그럼 어떻게 해야될까요?

키보드도 뭐 똑같습니다

출발은 바로하지 안되 response는 주는겁니다.

움직이기 이전 동작(출발자세) 같은 애니메이션을 작동시키는겁니다. 그리고 서버에서 데이터가 오면 그때 이동을 하는거죠... 이런식으로 동기화를 맞춘다면... 모든 플레이어가 그래도 나름 비슷한 환경에서(전체적으로 조금 늦게) 게임을 하는거겠죠. 적어도 억울한 사람은 없을겁니다. 내가 쟤보다 느리다는둥... 그런건없을거에요.

예전 P2P게임을 보신다면... 방장이 서버라서 방장컴퓨터에서 행동된 것은 무조건 진리요 사실이지만.. 방장이 아닌 플레이어가 한 행동의 패킷이 방장에게 도착했을때 방장이 아니라고 판단한다면... 그건 아닌거니까요... 이러면 얼마나 억울하겠어요ㅠㅠ

그렇기 때문에 정리를 좀 해본다면... 대부분의 로직은 서버에 넣는게 좋습니다.

이유는 클라이언트에 넣으면 동기화가 까탈스럽고 그리고 그 부분에 조금더 좋은 알고리즘을 적용시키려면 패치라는걸 꾸준히 해줘야됩니다. 반면 서버는 패치는 안해도되죠.

그리고 클라이언트는 최대한 viewer로 만드는 것이 좋습니다. 움직임에 대한 입력을 제외하고는 거의 뷰어로 만들어서 렌더링에 치중할 수있게끔 도와주는겁니다 서버가. Dedicate server의 표본이죠 서버가 모든걸 다 처리하고 클라이언트는 그저 받아서 행동만한다.

 음... 아까 P2P 게임에서 방장이 서버라서 억울한 경우가 생길 수 있다고 했는데요...

예전에는 이런 방식으로 저부분을 좀 완화했었어요.

뭐냐면요 Latency만큼 시간을 뒤로 돌려서 충돌을 체크하는거죠. 이런 방식을 쓰긴했는데... 뭐 요새는 쓰는지 모르겠습니다.

그럼 방향이 존재하지 않는 케이스라면 어떻게 될까요...

마우스로 누르거나 키보드로 눌렀을땐 분명 방향이라는게 존재할겁니다.

하지만 방향이 존재하지 않는 경우라면요..? 그럴땐 어떻게 해야될까 고민을 해봐야될겁니다.

음... 제가 일단 배운바로는 클라이언트는 더미 플레이어를 조작하고 그 좌표를 서버로 전송합니다. 그리고 서버에서는 그 더미 플레이어의 좌표를 가지고 갈수있는지 없는지 판단을 하고 그 판단의 결과로 진짜 플레이어의 좌표를 쏴주는 방식으로 처리하는거죠...

뭐... 클라이언트는 최소한의 로직이 들어가면 좋긴하지만 서버의 부담이 너무 막중해진다면 클라이언트에서 일부 후보를 추려놓고 그 후보들만 보내서 서버에서는 그 후보들중에서 고르게하는 방법도 있습니다.

충돌의 경우 그렇게 할 수 있겠죠. 100명의 적군이 있는데 총을 쐈을때 그중에 누구랑 충돌했는지 모르겠다면... 총알이랑 가까운 10명의 정보를 보내고 서버는 그중에서 누가 맞았는지 판단을 하는거죠. 물론 이런건 전적으로 클라이언트를 믿고있다는 가정하에 해야되므로... 핵으로 10명을 조작한다면... 뭐 어쩔수없는거죠 이런게 싫다면 전부 서버에서 처리해버리면 그만이니까요...

네... 뭐 동기화 얘기가 나온김에 좀 특이한 케이스도 하나 알아보겠습니다.

모두의 프레임을 동일하게 맞춘다 라는 개념의 동기화도 있습니다.

예전 스타크래프트1에서 이런 케이스를 사용했었는데요 그래서 중간에 누가 알트탭 누르고 아니면 윈도우키 눌러서 밖으로 나가버리면 다른 플레이어들은 드랍에 걸리게 됩니다 그리고 1분정도 지나고나서 그플레이어가 연결이 안되면 다른플레이어들이 쫒아낼수있는거죠. 한 프레임 프레임을 다 맞춰나가야 하기때문에 사양이 낮은 사람이 들어오거나 혹은 계속 게임 화면을 내려놓거나 한다면... 드랍이 걸리는겁니다...

이런 방식을 락스탭방식이라고 부릅니다.

음... 일단 서버의 동기화 방법이나 서버에 대한 아주 얕은 구조 얘기를 해보았는데요...

아마 현업자분들께서는 어떻게 하고 계신지 잘 모르겠습니다... 하지만 제 주관이 잔뜩 섞인 이글을 만약 현업자분들이 읽어주시는 그런 영광이있다면 하하... 요새 서버는 어떻게 되어가는지 공유 부탁드립니다

저같은 서린이에게 좋은 정보를 공유해주세요...

그럼 오늘도 긴글 읽어주셔서 정말 감사드립니다.

다음에는 더 좋은 정보를 들고 나오겠습니다. 그럼 안녕히계세요

Toplist

최신 우편물

태그