2025. 12. 1. 20:58ㆍGame/Web and Game Server

※ Reference
- 개복치를 위한 CPP 프로그래밍, 본인 제작(2025/인프런, 현재 비공개)
- 게임 서버 프로그래밍 교과서, 배현직 지음(2019/길벗)
- Computer Networking : A Top-down Approach, 8th edition by Jim kurose/Keitrh Ross
※ 경고사항
- 본 게시글을 읽으실때 Computer Network와 CPP에 대한 이해가 충분하지 않으시다면 많이 힘드실 수 있습니다.
- Computer Networking : A Top-down Approach의 경우 PPT가 공개되어 있어 해당 자료를 사용하나, 나머지 자료화면들은 아닌 경우가 있습니다. 물론 제가 만든거면 딱히 뭐라 안합니다만..
- ChatGPT/Gemeni/Claude의 도움을 받으시면 이해하기 더욱 쉬우나, Hallucination에 유의해 주세요. GPT의 경우 CODEX를 이용하시면 더욱 훌륭한 결과물을 얻을 수 있습니다.
일반적인 웹사이트는, 대게 서버가 HTML 파일 "등"을 던저주면 클라이언트(브라우저)가 화면에 띄워줍니다. 물론 상세하게 들어가면 서버 사이드 렌더링, 클라이언트 사이드 렌더링, 혼합 방식 등으로 복잡하지만.. 어쨋든 핵심은 "실시간 연결"이 필요 없다는 점입니다. 클라이언트가 HTTP Request(GET/POST)를 보내면 서버가 "200(ACK)"을 띄우고 웹사이트를 띄우는데 필요한 파일을 보내줍니다. 그리고는 연결을 종료시킵니다. (HTTP1.1, 2/3의 경우 연결 자체는 유지됩니다. 단지 서버가 먼저 말을 못할 뿐입니다.)
다만 이러한 경우를 게임에 그대로 적용하기는 어렵습니다. 서버와 클라이어트간에 지속적으로 데이터가 왔다 갔다 해야되는데, 데이터 하나 보내고 종료하고 다시 연결하고.. "요청을 보내고 응답을 기다리는" 뻘짓을 반복 할 수는 없습니다. 거기에 더해서 HTTP라는 문서 교환 규칙은 조금 복잡합니다. 즉 이말은 지연이 늘어지고 성능적으로 큰 손실을 봄을 의미합니다. (물론 데이터를 보내는 데에 HTTP를 사용하고, 데이터 내용물에 JSON과 같은 걸 쓰는 경우 또한 충분히 있습니다. 다만 AOS나 FPS같은 게임이면 좀 거시기 하겠죠.)
따라서 게임 서버는 대게 소켓 프로그래밍을 사용, 근원부터 바이너리로 지지고 볶아서 이러한 문제를 해결합니다. 물론 따지고 보면 HTTP도 소켓 프로그래밍을 이용합니다. 대충 Socket은 전화선, HTTP는 소켓을 타고 메시지를 어떻게 주고 받을지 정한 약속 같은 거니까요. 다만 HTTP가 복잡한 행정 서류 같은거라면, 게임에서 쓰는 방식은 그냥 메모에 아무렇게나 휘갈겨서 후다닥 전달해 주는 차이가 있습니다.

쨋든 소켓이라는 전화선으로 데이터를 주고 받고 잘 지지고 볶으면 되는 것은 알겠습니다. 그리고 그 전화선을 통해 "데이터 자체를 전달하는 프로토콜"에는 TCP/UDP가 있습니다.(데이터의 운반은 TCP/UDP, 데이터 이동 과정에서의 대화 법칙은 HTTP 등의 관할입니다!) 이때 딱히 몇개 날라가도 상관 없지만 실시간성이 중요한 데이터라면 UDP를 사용하는 편 입니다만, 그게 아니라면 대부분 TCP를 사용합니다. 나름 신뢰성 있는 친구니까요. 문제는 간혹 가다가 소켓으로 데이터를 주고 받을때, TCP를 사용 했음에도 데이터가 황천길로 사라지는 경우가 존재합니다.
이는 Socket Buffer의 존재 때문입니다. CPP를 공부할 때 입력 버퍼에 대해서 알게 되는데, 이 친구도 별반 다를 것이 없습니다. 소켓 각각이 송신 버퍼와 수신 버퍼를 가지게 되고, 데이터들은 여기를 일단 거치게 됩니다. 문제는 이 버퍼가 꽉 차서 새 데이터가 들어올 데가 없는 경우(Blocking)가 있다는 점 입니다! 따라서 프로세스가 제 때 데이터를 치우지 못한다면, TCP 프로토콜 상 속도를 조절하게 됩니다. (그리고 TCP Slow Start가 괜히 있는게 아니라는 걸 알게 되죠.)
위와 같은 경우를 Blocking Socket이라고 합니다. Blocking Socket은 신뢰도가 좀 많이 높습니다, 다만 여러 사람에게 데이터를 던져야 하는 경우에는 조금 머리가 아플 겁니다. 예를 들어서 1000명에게 데이터를 이걸로 던지려 한다면, 1000개의 스레드를 만들어서 각각에 소켓을 열어야 할거고 그만큼의 송신/수신 버퍼가 필요할 겁니다. 근데 송/수신 버퍼가 512kb만 되도 벌써 1GB가 넘어갑니다! Context Switching으로 인한 성능 손해는 더 말할 것도 없겠죠.물론 OS는 Non-Blocking Socket을 다행히도 지원 합니다.
그리고 이 얘기는 다음편에 이어 갈 예정이죠...
'Game > Web and Game Server' 카테고리의 다른 글
| [CPP] Socket Programming(2) : Non-Blocking Socket (0) | 2025.12.02 |
|---|