고성능 멀티스레드 MMORPG 서버 시스템 구현 프로젝트입니다. IOCP(I/O Completion Port) 기반의 비동기 네트워킹과 JobQueue를 활용한 Lock-free 아키텍처를 통해 높은 동시성과 확장성을 확보했습니다.
이 프로젝트는 학습 및 포트폴리오를 목적으로 개발되었으며, 실제 게임 서버에서 요구되는 핵심 기능들을 구현하고 있습니다.
-
Visual Studio 2022 필요 Installer에서 Python 개발, .NET 데스크톱 개발, C++ 사용한 데스크톱 개발, 데이터 스토리지 및 처리 설치
-
Shared 디렉토리에 있는
authserver.appsettings.json,gameserver.appsettings.json,sheetloader.example_service_key.json를 로컬 설정에 맞게 변경 후, 이름을appsettings.json과service-account-key.json으로 변경 후 각 폴더의 루트에 넣습니다. -
DB(ms-sql) 기준 AuthDb와 GameDb를 만들어줍니다. 테이블과 프로시져는 ORM으로 빌드 시 생성됩니다.
-
.sin을 열어 빌드시켜줍니다. Client는 DummyClient나 TestClientUnity(GUI)를 사용하시면 됩니다.
- IOCP 기반 C++ 게임 서버: Windows IOCP를 활용한 고성능 멀티스레드 비동기 I/O 처리
- gRPC + JWT 인증 시스템: .NET 9.0 기반 인증 서버, JWT 토큰 기반 보안
- Protocol Buffers: 효율적인 바이너리 직렬화 및 클라이언트-서버 통신
- 자동화된 코드 생성:
- PacketGenerator: Protocol Buffers 정의로부터 C++ Handler 및 C# Manager 자동 생성
- ProcedureGenerator: XML 스키마로부터 ORM Stored Proced ure 래퍼 자동 생성
- Google Sheets 연동: 게임 데이터(몬스터, 아이템 등)를 Google Sheets에서 JSON으로 자동 배포
- 인벤토리 시스템: 40슬롯, 아이템 스택, 실시간 DB 동기화
- 장비 시스템: 장착/해제 기능, 스탯 적용, 레벨 제한
- 파티 시스템: 파티 초대/수락/거절, 공개 파티, 강퇴 기능
- 레벨/전투 시스템: 경험치, 레벨업, 플레이어-몬스터 전투
- 채팅 시스템: 룸별 채팅, 전체 채팅
- 멀티 룸 시스템: 포털을 통한 맵 이동, 지역별 룸 매핑
- 몬스터 AI FSM: Patrol, Chase, Combat 상태 기반 몬스터 AI
- NPC 시스템: Component 기반 NPC (Dialog, Shop, Quest)
- 드롭 시스템: 몬스터 처치 시 아이템 드롭
본 프로젝트는 작업 유형에 따라 스레드를 3단계로 분리하여 효율적인 멀티스레드 처리를 구현했습니다.
-
IOCP Worker (5개): 네트워크 I/O 전담
IocpCore::Dispatch()를 통해 소켓 읽기/쓰기 완료 이벤트 처리- 패킷을 수신하면 해당 Room의 JobQueue에 작업을 위임하고 즉시 다음 I/O 처리
-
Shard Worker (2개): Room별 게임 로직 처리
- 각 Shard는 2개의 Room을 담당 (총 3개 Room → 2개 Shard)
GlobalQueue에서 JobQueue를 꺼내 실행하는 방식- Room 내부 상태(플레이어, 몬스터 등)는 해당 Shard Worker에서만 접근
-
DB Worker (1개): 비동기 데이터베이스 작업
- 캐릭터 저장, 인벤토리 업데이트, 장비 변경 등 모든 DB 작업 처리
std::packaged_task와std::future를 활용한 비동기 작업 처리
이 서버는 대부분의 게임 로직에서 명시적인 Lock 없이 동작합니다.
[클라이언트 패킷 수신]
↓
[IOCP Worker] ← Packet 수신
↓
Room->DoAsync(Lambda) ← JobQueue에 작업 추가
↓
[Shard Worker] ← JobQueue에서 작업 꺼내 실행
↓
[Room 내부 로직] ← _players, _monsters 등 Room 상태 접근
핵심 원리:
- 각 Room은 독립적인
JobQueue를 보유 - IOCP 스레드는 패킷 수신 시
Room->DoAsync(lambda)로 작업을 JobQueue에 추가하고 즉시 반환 - Room 내부 데이터(
_players,_monsters등)는 해당 Room을 담당하는 Shard Worker에서만 접근 - 단일 스레드 접근 보장으로 Lock이 불필요하며, JobQueue를 통한 비동기 처리로 높은 동시성 확보
auto future = DbDispatcher::EnqueueRet([=](DBConnection& conn) {
// DB 작업 수행
return CharacterRepository::GetCharacterStat_DB(conn, characterId);
});
// 게임 로직 계속 진행 가능
// ...
// 필요 시점에 결과 대기
auto result = future.get();- DB 작업을 별도 스레드에서 처리하여 게임 로직 블로킹 방지
packaged_task로 작업을 패키징하고,future로 결과 수신
모든 DB 작업은 Repository 클래스를 통해 접근하여 코드 일관성과 유지보수성을 확보했습니다.
- CharacterRepository: 캐릭터 생성, 조회, 업데이트, 삭제
- InventoryRepository: 인벤토리 아이템 CRUD
- EquipmentRepository: 장비 인스턴스 및 장착 상태 관리
- AccountRepository: 계정 인증 및 사용자 정보
- DropTableRepository: 몬스터 드롭 테이블 관리
GameDB.xml에 정의된 테이블 스키마와 Stored Procedure를 기반으로 GenProcedures.h가 자동 생성됩니다. 이를 통해 타입 안전성과 개발 생산성을 확보했습니다.
- Room 기반 멀티스레드 처리: 각 Room은 독립적인 JobQueue를 통해 게임 로직을 비동기 처리
- Singleton Manager/Service 구조: 중앙화된 관리 클래스로 시스템 간 통신 및 상태 관리
- 자동 저장 시스템:
- 3분 주기 자동 저장
- 룸 전환 시 자동 저장
- 연결 해제 시 자동 저장
- Component 기반 NPC 시스템: Dialog, Shop, Quest 등 기능을 Component로 분리하여 확장 가능한 구조
Protocol Buffers 정의 파일(.proto)을 파싱하여 C++ 패킷 핸들러와 C# 패킷 매니저를 자동 생성합니다.
cd Protocol
GenPackets.bat생성 파일:
ClientPacketHandler.h/cpp: C++ 서버 패킷 핸들러PacketManager.cs: C# 클라이언트 패킷 매니저
GameDB.xml을 파싱하여 ORM Stored Procedure 래퍼를 자동 생성합니다.
cd Common/Procedures
GenProcs.bat생성 파일:
GenProcedures.h: Stored Procedure 래퍼 클래스
Google Sheets에서 게임 데이터(몬스터 스탯, 아이템 정보 등)를 JSON으로 자동 다운로드하여 서버에 배포합니다.
root/
├── AuthServer/ # gRPC 인증 서버 (.NET 9.0)
├── GameServer/ # TCP 게임 서버 (C++)
├── IocpCore/ # IOCP 네트워킹 코어 라이브러리
├── DummyClientCS/ # C# 테스트 클라이언트
├── TestClientUnity/ # Unity 클라이언트
├── Protocol/ # Protocol Buffers 정의 및 생성 스크립트
├── Common/Procedures/ # DB Procedure 생성 도구
├── Tools/ # 코드 생성 유틸리티
└── third_party/ # 외부 의존성 (gRPC, protobuf 등)
GameServer는 물리적 폴더 분리 없이 파일 이름 패턴으로 논리적 분류를 합니다.
GameSession: 클라이언트 연결 세션GameSessionContainer: 세션 컨테이너GameSessionAccessor: 스레드 안전 세션 접근
Player: 플레이어 엔티티PlayerCombatSystem: 플레이어 전투 로직PlayerPorts: 플레이어 인터페이스
MonsterService: 몬스터 서비스MonsterContainer: 몬스터 컨테이너MonsterCombatSystem: 몬스터 전투 AIMonsterMovementSystem: 몬스터 이동 로직MonsterSpawnerSystem: 몬스터 스폰 시스템MonsterTypes,MonsterPorts: 몬스터 타입 정의MonsterDataParser: 몬스터 데이터 파싱
Room: 룸 베이스 클래스FieldRoom: 전투 필드 룸TownRoom: 마을 룸RoomManager: 룸 관리
DBWorker: DB 작업 워커 스레드DBDisPatcher: DB 작업 디스패처 (PackagedTask & Future)AccountRepository: 계정 레포지토리CharacterRepository: 캐릭터 레포지토리InventoryRepository: 인벤토리 레포지토리EquipmentRepository: 장비 레포지토리DropTableRepository: 드롭 테이블 레포지토리GenProcedures: 자동 생성 ORM SP 래퍼
InventoryCore,InventorySystem: 인벤토리 핵심 로직EquipmentCore,EquipmentSystem: 장비 핵심 로직EquipmentManager: 장비 관리자EquipmentDataParser: 장비 데이터 파싱
ItemManager: 아이템 관리자ItemDataParser: 아이템 데이터 파싱DropManager: 드롭 관리자DropDataParser: 드롭 데이터 파싱
Party: 파티 엔티티PartyService: 파티 서비스PartyManager: 파티 관리자
Npc: NPC 엔티티NpcManager: NPC 관리자NpcDialogComponent,NpcDialogManager: NPC 대화 시스템NpcQuestComponent: NPC 퀘스트 컴포넌트NpcShopComponent,NpcShopDataManager: NPC 상점 시스템
MapData: 맵 데이터 로딩 및 관리SpawnPointDataParser: 스폰 포인트 파싱
ClientPacketHandler: 자동 생성 패킷 핸들러ProtocolHelper: 프로토콜 헬퍼 함수Protocol.pb: 자동 생성 Protocol Buffers 클래스
AppConfig: 애플리케이션 설정JwtAuth: JWT 토큰 검증Account: 계정 엔티티
ShardBoot: Shard 초기화 및 Room 생성GlobalQueueShard: Shard별 GlobalQueue 관리SharedOwner: 공유 리소스 소유권 관리IJobQueueOwner: JobQueue 소유자 인터페이스
EntityCore: 엔티티 핵심 로직GeometryCore: 2D 좌표, 방향, 충돌 처리TypeCore: 핵심 타입 정의TimeUtils: 시간 유틸리티RandomUtils: 랜덤 유틸리티JsonFileUtils,JsonDataParser: JSON 파싱StringConvert: 문자열 변환
IocpCore는 재사용 가능한 네트워킹 라이브러리로, 게임 서버뿐 아니라 다른 서버에도 활용 가능합니다.
IocpCore: IOCP 메인 클래스IocpEvent: IOCP 이벤트 처리Service: 네트워크 서비스 베이스Session: 세션 베이스 클래스Listener: TCP 리스너
Memory: 메모리 관리MemoryPool: 메모리 풀링Allocator: 커스텀 할당자ObjectPool: 객체 풀링
ThreadManager: 스레드 풀 관리Lock: SpinLock 등 락 구현LockQueue: 스레드 안전 큐DeadLockProfiler: 데드락 프로파일러
Job: 작업 베이스 클래스JobQueue: 작업 큐JobTimer: 타이머 기반 작업 스케줄링GlobalQueue: 전역 작업 큐
SendBuffer: 송신 버퍼RecvBuffer: 수신 버퍼BufferReader: 바이너리 읽기BufferWriter: 바이너리 쓰기
DBConnection: MySQL 연결 래퍼DBConnectionPool: 연결 풀링DBBind: SQL 파라미터 바인딩DBModel: DB 모델 베이스DBSynchronizer: DB 동기화DBConnGuard: RAII 연결 가드
NetAddress: 네트워크 주소 처리SocketUtils: 소켓 유틸리티
CoreGlobal: 전역 변수CorePch: 프리컴파일 헤더CoreTLS: 스레드 로컬 스토리지CoreMacro: 공통 매크로Types: 타입 정의TypeCast: 타입 캐스팅Container: STL 컨테이너 정의
FileUtils: 파일 I/OConsoleLogger: 콘솔 로깅XMLParser: XML 파싱 (RapidXML)
설정 파일을 Github에 업로드 했습니다.
크게 2가지 환경 종속적인 부분이 있습니다.
DB의 경우 로컬 SQL Server의 경로, driver 등 설치되어 있는 경로를 정확히 입력해야 하며, 이를 잘못 입력할 시 빌드가 되지 않을 수 있습니다.
또한 빌드 전에 SQL에 직접 접근해 GameDb와 AuthDb 데이터베이스를 생성해야 하고, 빌드 시 GameServer의 경우 GameDB.xml을 통해 자동으로 ORM이 생성되지만, AuthServer의 경우 없습니다.
아래의 T-SQL을 사용하여 직접 Table을 만들어주어야 합니다
CREATE TABLE [dbo].[Users]
(
[Id] INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
[Email] NVARCHAR(100) NOT NULL UNIQUE,
[PasswordHash] NVARCHAR(200) NOT NULL,
[CreatedAt] DATETIME2(0) NOT NULL
CONSTRAINT DF_Users_CreatedAt
DEFAULT (SYSUTCDATETIME())
)# Visual Studio 솔루션 빌드
msbuild 2d-mmorpg-replica.sln /p:Configuration=Debug /p:Platform=x64혹은 .sin 파일을 visual studio 2022로 열어 직접 빌드
빌드를 하게 되면 빌드 전 이벤트로 ORM & Proto 파일 등 자동생성되니 빌드는 필수 입니다.