목록Game Dev (261)
KoreanFoodie's Study
[C++ 게임 서버] 6-7. JobTimer 핵심 : 1. JobTimer 를 사용하면, Job 의 배분을 일정 주기 이후 실행하도록 균등하게 배분할 수 있다. 2. 세션이 종료될 때 Memory Leak 이 일어나지 않도록 종료 처리를 잘 해주자. 이전에 Job 의 처리를 쓰레드에게 어느 정도 균등하게 분배하기 위해 Tick 과 소유권에 대한 개념을 도입했다. 그런데 각 쓰레드 별로 Tick 을 루프를 돌며 체크하는 일은 엄청난 낭비가 아닐 수 없다. 😅 이 문제를 해결하기 위해, Global 하게 JobTimer 라는 녀석을 도입해 일정 시간 후, Job 을 알아서 처리하도록 만들어 보자. JobTimer.h struct JobData { JobData(weak_ptr owner, JobRef jo..
[C++ 게임 서버] 6-6. JobQueue #5 핵심 : 1. JobQueue 방식을 이용해 쓰레드가 Job 을 처리할 때 발생하는 병목 현상 문제를 해결해 보자. 2. GlobalQueue 와 Tick 의 개념을 활용해, 이전 글에서 언급했던 두 가지 병목 현상을 해결할 수 있다. 3. 서버 로직과 클라 로직은 각각 분리하여 돌아가도록 구현하는 것이 좋다. 다만 이번 글에서는, DoWorkerJob 함수에서 모든 로직을 한꺼번에 처리하도록 구현하였다. 이번 시간에는 저번 글에서 지적했던 병목 현상을 해결하기 위해, GlobalQueue 와 시간 제한을 주는 방식을 도입해 보자. 일단 Job 부분은 달라진 것이 없는데... JobQueue 에서 Execute 를 해주는 로직을 일부 수정할 것이다. 거..
[C++ 게임 서버] 6-5. JobQueue #4 핵심 : 1. JobQueue 를 템플릿 버전으로 만들어 LockQueue 라는 이름으로 바꿔보자. 2. Job 에 대한 처리를 Push 를 하는 쓰레드 중 일부가 실제로 처리하도록 만들 수 있다. 그럼 메인 서버에서 FlushJob 을 하던 부분을 특정 쓰레드가 담당할 것이다. 3. 2번에 대한 처리를 할 때는, 동기화에 대한 부분과 병목 현상에 대한 부분을 모두 고려해야 한다. 이번 시간에는, Job 을 처리하는 부분을 조금 더 고도화시켜볼 것이다. 또한, 이전에는 GameServer 에서 한 녀석이 FlushJob 을 호출하면서 Job 을 꺼내 하나하나 처리했는데, 이 부분을 그냥 Job 을 추가하는 쓰레드 중 하나가 알아서 처리하도록 만들 것이다..
[C++ 게임 서버] 6-4. JobQueue #3 핵심 : 1. 이번 글에서는 JobSerializer 를 이용해, 람다 함수를 SharedPtr 로 만들어 Push 해 줌으로써 좀 더 간편하게 Job 관리하는 방법을 알아보자. 2. 람다와 SharedPtr 를 함께 쓴다고 해서 Memory Leak 이 일어나지는 않는다. 만약 문제가 있다면 람다와 SharedPtr 를 함께 사용해서 문제가 생기는 것이 아니라, 기본적인 설계가 잘못된 것이다. 이번 시간에는 기존에 만들었던 Job 을 좀 더 간편하게 사용할 수 있도록 구조를 약간 수정해 보자. 먼저 Job 을 아래와 같이 ServerCore 에 만들어줄 것이다. /*--------- Job ----------*/ using CallbackType = ..
[C++ 게임 서버] 6-3. JobQueue #2 핵심 : 1. Job 별로 클래스 상속을 무한히 늘려나가기 보다, Functor 와 Tuple 을 이용해 각 Job 을 간편하게 추가해 보자. 2. C++ 17 에서는 std::apply 를, C++ 11 에서는 Template Meta Programming 을 이용해 특정 Functor 에 임의의 갯수의 인자를 넘겨주는 기능을 구현할 수 있다. 저번 시간에는 Job 과 JobQueue 에 대한 개념을 간단하게 소개했다. 그런데, 사실 Job 이 늘어날 때마다 이를 상속해서 클래스를 무한히 늘려나가는 방식은... Job 의 갯수가 늘어난다고 하면 매우 끔찍한 결과를 초래할 수 있다. Job 을 추가하는 과정을 조금 간략화하기 위해, 템플릿을 이용해 각 ..
[C++ 게임 서버] 6-2. JobQueue #1 핵심 : 1. Command 패턴은, 실행될 동작에 대한 인터페이스를 만들어 구체적인 동작은 해당 인터페이스를 상속 받은 객체에서 결정하도록 하는 설계 기법이다. 2. Command 패턴과 JobQueue 를 이용하면, 이전에 Broadcast 로 인한 동작의 병목 현상(LOCK 으로 인한)을 줄일 수 있다. 이전 시간에 간단한 채팅 서버를 만들어 보았다. 다만 이전 방식은 Broadcast 를 하는 부분에서 병목 현상이 심각할 수 있다는 단점이 있었는데... 이를 해결하기 위해, 우리는 JobQueue 를 만들어 순차적으로 이 문제를 해결해볼 것이다. 일단 이번 시간에는 Command 패턴을 이용해 조악하게나마 JobQueue 를 구축해 보자. Com..
[C++ 게임 서버] 6-1. 채팅 실습 핵심 : 1. Chat 서버를 만들어보자. 간단하게는 채팅이 전파될 Room 과 채팅 패킷만 만들어 주면 된다. 2. 채팅을 전파할 때마다, Room 에서 WRITE_LOCK 을 잡으면 병목현상이 생길 수 있다. 이를 해결하기 위해, 추후 JobQueue 를 도입할 것이다. 이번에는 채팅 패킷을 만들어 보면서, 간단하게 실제로 패킷을 추가하는 작업을 어떻게 진행하는지 살펴볼 것이다. 일단, 우리가 작업했던 Protocol.proto 를 다음과 같이 수정해 주자. syntax = "proto3"; package Protocol; import "Enum.proto"; import "Struct.proto"; message C_LOGIN { } message S_LOG..
[C++ 게임 서버] 5-9. 패킷 자동화 #2 핵심 : 1. 파이썬과 jinja2 를 이용해, 패킷 핸들러 코드를 자동으로 생성해 보자. 2. 이 포스팅에서 만든 ProtoParser 는 Protocol.proto 의 패킷 명세를 읽어 PacketHandler 의 코드를 자동으로 생성한다. 저번 시간에 패킷 자동화를 위한 밑작업(?) 을 보여준 바 있다. 사실 제대로 패킷 자동화를 구축하기 위해서는, data-driven 하게 작업이 이루어져야 할 것이다. 간단한 Flow 를 생각하면 다음과 같다 : Protocol.proto 에 우리가 원하는 패킷(메시지)을 선언한다. 자동화 툴이 돌아가서 Packet 과 PacketHandler 클래스를 생성한다. 프로그래머는 각 패킷에 대한 커스텀 동작만 직접 구..
[C++ 게임 서버] 5-8. 패킷 자동화 #1 핵심 : 1. 효율적인 작업을 위해, 패킷이 변동될 때 빌드를 하면 관련 protoc 파일 등이 자동으로 업뎃되게 만들면 좋다. 배치파일과 .vcxproj 를 잘 수정해 보자. 2. 초기화 단계에서 각 패킷 별로 호출되어야 하는 함수를 Functor 로 만들어 각 패킷에 대응시켜 놓으면, 각 컨텐츠 담당자는 패킷이 추가될 때 해당 패킷에 대한 구현만 신경쓰면 된다. 저번 시간에는 Protobuf 를 세팅하면서, 패킷 작업을 어떻게 하면 되는지에 대해 배웠다. 그런데 사실 돌이켜 보면 불편한 점이 이곳 저곳에 산재한다는 느낌이 든다. 왜냐하면 결국 우리가 패킷을 만들거나 수정하면, .protoc 파일을 매번 새로 생성해 줘야 하는데, 심지어 이 작업을 Gam..
[C++ 게임 서버] 5-7. Protobuf 핵심 : 1. protobuf 는 구조화된 데이터를 직렬화하는 방식으로, 구글에서 제공하는 툴을 의미하기도 한다. 2. protobuf 를 사용하면 임시 객체에 대한 복사는 발생할 수도 있으나, 직렬화와 역직렬화 과정이 매우 편리해진다는 장점이 있다. 3. protobuf 는 인터페이스가 간단하고 명확하며, 다른 언어 및 OS 를 사용하는 타 서버와의 연동이 쉬워 협업에도 매우 유리하다. 이번 시간에는 구글에서 만든 데이터 직렬화 툴을 지금까지 만든 샘플 프로젝트에 적용해 볼 것이다. 이번에는 결과만 보여주는 것이 아니라, 설치 및 세팅하는 과정을 자세히 기록할 것이니, 추후 세팅에 어려움을 겪을 때 이 글이 도움이 되었으면 좋겠다. 🤗 먼저, protobu..