Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Network / Async / DB 처리 구조 분석 보고서

  • 최초 작성: 2026-02-26 최종 업데이트: 2026-03-02
  • 기준 리포지토리: NetworkModuleTest
  • 분석 기준: ServerEngine, TestServer, DBServer 실제 구현 코드
  • 목적: 네트워크 처리, 비동기 처리, DB 처리의 현재 구조와 데이터 흐름을 코드 기준으로 정리

주요 업데이트 (2026-03-02)

  • 비동기 고도화: KeyedDispatcher(직렬화), TimerQueue(타이머), AsyncScope(협력 취소), Send 백프레셔, NetworkEventBus(이벤트 버스) 추가
  • AsyncScope 풀 재사용 버그 수정: 세션 풀 재사용 시 mCancelled=true 잔존 문제 → AsyncScope::Reset() 추가로 해결
  • Linux Docker 테스트: Ubuntu 22.04 컨테이너에서 epoll + io_uring 양 백엔드 통합 테스트 PASS
  • Core/Memory 버퍼 모듈: 플랫폼 독립 IBufferPool + StandardBufferPool / RIOBufferPool / IOUringBufferPool
  • 성능: Windows 1000 클라이언트 PASS, Server WS 143.6 MB (최적화 후)

Diagram Map

Diagram File
Architecture Overview assets/01-architecture-overview.svg
Session UML assets/02-session-uml.svg
Client Lifecycle Sequence assets/03-client-lifecycle-sequence.svg
Async DB Flow Sequence assets/04-async-db-flow-sequence.svg
Graceful Shutdown Sequence assets/05-graceful-shutdown-sequence.svg
DB Reconnect Sequence assets/06-db-reconnect-sequence.svg

1. 요약

이 프로젝트는 INetworkEngine(상위 추상화)와 AsyncIOProvider(하위 플랫폼 백엔드)로 분리된 2계층 구조를 사용한다.

  • 네트워크 처리: 플랫폼별 엔진(Windows/Linux/macOS)이 수락/완료 이벤트를 처리하고, 공통 로직은 BaseNetworkEngine이 담당
  • 비동기 처리: I/O 워커 스레드 + 로직 스레드풀 + DB 전용 작업큐(DBTaskQueue, OrderedTaskQueue)로 역할 분리
  • DB 처리: IDatabase 추상화 위에 SQLite/Mock/ODBC 구현을 두고, TestServer는 비동기 큐 기반으로 DB 작업을 오프로딩

핵심 특징:

  • Windows: RIO 우선, 실패 시 IOCP 폴백
  • Linux: io_uring 우선, 실패 시 epoll 폴백
  • macOS: kqueue
  • TestServer의 접속/종료 DB 기록은 이벤트 핸들러 -> DBTaskQueue 경로로 비동기 처리
  • 종료 시 DBTaskQueue 드레인 -> DB 해제 -> 네트워크 종료 순서로 graceful shutdown 수행

2. 분석 범위

2.1 네트워크 엔진

  • Server/ServerEngine/Network/Core/NetworkEngine.h
  • Server/ServerEngine/Network/Core/BaseNetworkEngine.h
  • Server/ServerEngine/Network/Core/BaseNetworkEngine.cpp
  • Server/ServerEngine/Network/Core/NetworkEngineFactory.cpp
  • Server/ServerEngine/Network/Core/AsyncIOProvider.h
  • Server/ServerEngine/Network/Core/AsyncIOProvider.cpp
  • Server/ServerEngine/Network/Platforms/WindowsNetworkEngine.cpp
  • Server/ServerEngine/Network/Platforms/LinuxNetworkEngine.cpp
  • Server/ServerEngine/Network/Platforms/macOSNetworkEngine.cpp
  • Server/ServerEngine/Network/Core/Session.h
  • Server/ServerEngine/Network/Core/Session.cpp
  • Server/ServerEngine/Network/Core/SessionManager.cpp

2.2 TestServer (게임 서버)

  • Server/TestServer/src/TestServer.cpp
  • Server/TestServer/src/ClientSession.cpp
  • Server/TestServer/src/ClientPacketHandler.cpp
  • Server/TestServer/src/DBTaskQueue.cpp
  • Server/TestServer/src/DBServerPacketHandler.cpp
  • Server/TestServer/main.cpp

2.3 DBServer

  • Server/DBServer/src/TestDBServer.cpp
  • Server/DBServer/src/ServerPacketHandler.cpp
  • Server/DBServer/src/OrderedTaskQueue.cpp
  • Server/DBServer/src/ServerLatencyManager.cpp
  • Server/DBServer/main.cpp

Architecture Overview

3.1 계층 구조

INetworkEngine가 외부 API를 정의하고(Initialize/Start/Stop/SendData/CloseConnection), BaseNetworkEngine이 공통 동작을 구현한다.

  • 공통: 세션 조회/제거, 이벤트 콜백 등록, 통계 집계
  • 플랫폼 특화: 소켓 생성, accept 루프, completion 처리

코드 포인트:

  • 인터페이스: Server/ServerEngine/Network/Core/NetworkEngine.h:72
  • 공통 구현: Server/ServerEngine/Network/Core/BaseNetworkEngine.cpp:28

3.2 플랫폼 백엔드 선택

엔진 팩토리(CreateNetworkEngine("auto"))와 AsyncIO 팩토리가 폴백 체인을 제공한다.

  • Windows: RIO -> IOCP
    • Server/ServerEngine/Network/Core/NetworkEngineFactory.cpp:24
    • Server/ServerEngine/Network/Core/AsyncIOProvider.cpp:74
  • Linux: io_uring -> epoll
    • Server/ServerEngine/Network/Core/NetworkEngineFactory.cpp:58
    • Server/ServerEngine/Network/Core/AsyncIOProvider.cpp:104
  • macOS: kqueue
    • Server/ServerEngine/Network/Core/NetworkEngineFactory.cpp:105

Session UML

3.3 연결 수립부터 세션 생성까지

플랫폼 엔진 AcceptLoop() 공통 흐름:

  1. accept()로 소켓 수락
  2. SessionManager::CreateSession()로 세션 생성
  3. AsyncIOProvider::AssociateSocket()으로 백엔드 연동
  4. 로직 스레드풀에서 OnConnected + Connected 이벤트 실행
  5. Recv 등록

Windows 기준 코드:

  • accept 루프: Server/ServerEngine/Network/Platforms/WindowsNetworkEngine.cpp:128
  • 소켓 associate: .../WindowsNetworkEngine.cpp:167
  • 연결 이벤트 비동기 실행: .../WindowsNetworkEngine.cpp:188

Client Lifecycle Sequence

3.4 수신 처리와 패킷 재조립

수신 완료 처리(ProcessCompletions)에서 Recv 완료를 BaseNetworkEngine::ProcessRecvCompletion()으로 전달한다.

  • 데이터는 로직 스레드풀로 전달된 후 Session::ProcessRawRecv() 실행
  • ProcessRawRecv()는 TCP 스트림을 PacketHeader(size,id) 기준으로 재조립
  • 유효하지 않은 크기/오버플로우 탐지 시 세션 종료

코드 포인트:

  • completion 처리: Server/ServerEngine/Network/Platforms/WindowsNetworkEngine.cpp:233
  • 공통 recv 완료: Server/ServerEngine/Network/Core/BaseNetworkEngine.cpp:255
  • TCP 재조립: Server/ServerEngine/Network/Core/Session.cpp:445

3.5 송신 처리

송신 경로는 플랫폼별로 나뉜다.

  • Windows + RIO: Session::Send()에서 provider SendAsync() 직행
  • 그 외(WSASend/epoll/kqueue): mSendQueue에 enqueue 후 PostSend()로 비동기 송신

SessionmSendQueueSize(atomic)와 mIsSending(CAS)로 락 경쟁을 줄이고 중복 송신을 방지한다.

코드 포인트:

  • 송신 진입: Server/ServerEngine/Network/Core/Session.cpp:155
  • 큐 플러시/CAS: .../Session.cpp:248
  • 실제 PostSend: .../Session.cpp:261

3.6 이벤트 스레드 일관성

OnDisconnectedCloseConnection() 경로와 recv 오류 경로 모두 로직 스레드풀로 전달되어 실행된다. 즉, 콜백 호출 스레드가 일관되게 유지된다.

코드 포인트:

  • CloseConnection 경로: Server/ServerEngine/Network/Core/BaseNetworkEngine.cpp:155
  • recv 오류 경로: .../BaseNetworkEngine.cpp:264

4.1 공통 스레드풀/큐

  • ThreadPool은 내부적으로 SafeQueue를 사용
  • Submit() 시 큐가 가득 차면 작업 드롭 후 경고 로그
  • 워커에서 예외를 삼켜 프로세스 전체 실패를 방지

코드 포인트:

  • Server/ServerEngine/Utils/ThreadPool.h:22
  • Server/ServerEngine/Utils/SafeQueue.h:18

Async DB Flow Sequence

4.2 TestServer의 DBTaskQueue (논블로킹 DB)

현재 기본 경로에서 TestServer는 연결 이벤트를 직접 받아 DBTaskQueue에 작업을 enqueue한다.

  • OnClientConnectionEstablished -> RecordConnectTime
  • OnClientConnectionClosed -> RecordDisconnectTime
  • Stop() -> active session snapshot -> RecordDisconnectTime

코드 포인트:

  • 이벤트 핸들러: Server/TestServer/src/TestServer.cpp:449, :472
  • 큐 enqueue / 라우팅: Server/TestServer/src/DBTaskQueue.cpp:347, :385
  • 워커 실행: .../DBTaskQueue.cpp:536

중요 설계:

  • 현재 런타임 설정은 Initialize(1, ...)
  • 구현 자체는 워커별 독립 큐 + sessionId % workerCount 라우팅으로 같은 세션 순서를 보장

코드 포인트:

  • 워커 구조 / 라우팅: Server/TestServer/include/DBTaskQueue.h:70, :154
  • TestServer 현재 설정값: Server/TestServer/src/TestServer.cpp:131

4.3 WAL 기반 복구

DBTaskQueue는 WAL(db_tasks.wal)로 크래시 복구를 지원한다.

  • enqueue 전 P|...(pending) 기록
  • 성공 처리 후 D|seq 기록
  • 재시작 시 WAL(+백업 .bak)을 병합 파싱해 미완료 작업만 재큐잉

코드 포인트:

  • pending/done 기록: Server/TestServer/src/DBTaskQueue.cpp:538, :574
  • 복구 로직: .../DBTaskQueue.cpp:597

4.4 OrderedTaskQueue (DBServer)

TestDBServer는 serverId 단위 순서 보장을 위해 OrderedTaskQueue를 사용한다.

  • 내부적으로 KeyedDispatcher 사용
  • 같은 key(serverId)는 같은 worker queue로 라우팅
  • worker FIFO로 key 단위 순서 보장

코드 포인트:

  • facade: Server/DBServer/src/OrderedTaskQueue.cpp:29
  • keyed dispatch: .../OrderedTaskQueue.cpp:109
  • dispatcher 구현: Server/ServerEngine/Concurrency/KeyedDispatcher.h:30

DB Reconnect Sequence

4.5 DB 서버 재연결 비동기 루프 (TestServer)

Windows 경로에서 TestServer는 DB 연결 끊김 시 재연결 스레드를 실행한다.

  • 기본 지수 백오프: 1s -> 2s -> 4s ... max 30s
  • 예외: WSAECONNREFUSED(10061)은 1초 고정 간격 재시도
  • condition_variableStop() 시 즉시 깨어나도록 설계

코드 포인트:

  • 재연결 루프: Server/TestServer/src/TestServer.cpp:583
  • 에러 구분: .../TestServer.cpp:629

5.1 공통 DB 추상화 계층

DB 레이어는 IDatabase / IStatement 인터페이스 기반으로 구현체를 교체 가능하게 설계되어 있다.

  • 구현체: MockDatabase, SQLiteDatabase, ODBCDatabase, OLEDBDatabase
  • 생성: DatabaseFactory::CreateDatabase()

코드 포인트:

  • 인터페이스: Server/ServerEngine/Interfaces/IDatabase.h:29
  • 팩토리: Server/ServerEngine/Database/DatabaseFactory.cpp:19

5.2 TestServer 로컬 DB 경로

TestServer::Initialize()에서 로컬 DB를 선택한다.

  • dbConnectionString 비어있음: MockDatabase
  • 값 있음: SQLiteDatabase + 해당 파일 경로

선택된 DB 인스턴스를 DBTaskQueue에 주입하고, 큐에서 아래 테이블을 보장한다.

  • SessionConnectLog
  • SessionDisconnectLog
  • PlayerData

코드 포인트:

  • DB 선택/주입: Server/TestServer/src/TestServer.cpp:81
  • 큐 테이블 보장: Server/TestServer/src/DBTaskQueue.cpp:73

5.3 TestDBServer DB 관련 처리

TestDBServerServerPacketHandler + ServerLatencyManager + OrderedTaskQueue 조합으로 동작한다.

  • ServerPingReq 수신 시 RTT 계산 후 RecordLatency
  • DBSavePingTimeReq 수신 시 SavePingTime 실행 후 응답 패킷 전송

코드 포인트:

  • 핸들러 라우팅: Server/DBServer/src/ServerPacketHandler.cpp:40
  • RTT 기록: .../ServerPacketHandler.cpp:116
  • ping 저장: .../ServerPacketHandler.cpp:196

현재 상태(중요):

  • TestDBServer 경로에는 ServerLatencyManager::SetDatabase() 주입 코드가 없음
  • ServerLatencyManager::ExecuteQuery()는 DB 미주입 시 true 반환(log-only)

즉, 현재 기본 실행 경로에서는 메모리 통계/로그 중심이며, 영구 저장은 DB 주입이 연결되어야 활성화된다.

코드 포인트:

  • TestDBServer 초기화: Server/DBServer/src/TestDBServer.cpp:68
  • DB 미주입 시 log-only: Server/DBServer/src/ServerLatencyManager.cpp:331

5.4 대체/실험 경로: DBServer.cpp (제거됨)

DBServer.cpp는 데드 코드로 확인되어 삭제되었습니다. 유일한 실행 경로는 TestDBServer입니다.

6.1 Client -> TestServer

  1. 클라이언트 TCP 접속
  2. 엔진 accept 후 Session 생성/associate
  3. SessionManager::CreateSession()Core::Session을 생성/초기화
  4. SetSessionConfigurator()가 recv 콜백을 부착
  5. NetworkEvent::Connected -> OnClientConnectionEstablished() -> DBTaskQueue enqueue
  6. 클라이언트 SessionConnectReq 처리 후 SessionConnectRes 반환
  7. 주기적 PingReq/PongRes

관련 코드:

  • accept / CreateSession: Server/ServerEngine/Network/Platforms/WindowsNetworkEngine.cpp:128, :175
  • session configurator: Server/ServerEngine/Network/Core/SessionManager.h:48
  • 접속 기록 enqueue: Server/TestServer/src/TestServer.cpp:449
  • 핸드셰이크 처리: Server/TestServer/src/ClientPacketHandler.cpp:102

6.2 TestServer <-> TestDBServer

  1. TestServer가 ConnectToDBServer()로 별도 소켓 연결(Windows)
  2. TimerQueue::ScheduleRepeat()SendDBPing()을 주기 호출
  3. TestDBServer가 ServerPongRes 응답
  4. 주기적으로 PKT_DBSavePingTimeReq 전송/응답
  5. 끊김 시 DBReconnectLoop 재시도

관련 코드:

  • 연결/스레드 시작: Server/TestServer/src/TestServer.cpp:336
  • ping 스케줄링: .../TestServer.cpp:430
  • DBServer 패킷 처리: Server/DBServer/src/ServerPacketHandler.cpp:116

Graceful Shutdown Sequence

7.1 TestServer

Stop()에서 아래 순서를 지킨다.

  1. DB 재연결 루프 깨움 및 join
  2. 연결 중 세션의 disconnect 기록 enqueue
  3. DBTaskQueue->Shutdown()으로 큐 드레인
  4. 로컬 DB disconnect
  5. DB 서버 소켓 disconnect
  6. 클라이언트 엔진 stop

코드 포인트:

  • 전체 순서: Server/TestServer/src/TestServer.cpp:165

7.2 TestDBServer

  1. 네트워크 엔진 stop
  2. OrderedTaskQueue shutdown(남은 작업 처리)
  3. ServerLatencyManager shutdown

코드 포인트:

  • Server/DBServer/src/TestDBServer.cpp:160

8.1 강점

  • 네트워크/로직/DB 비동기 경로 분리 명확
  • 플랫폼 폴백 체인과 공통 추상화 정리됨
  • DBTaskQueue WAL 복구로 종료/크래시 안정성 강화
  • 재연결 정책(ECONNREFUSED 분리)으로 운영 복원력 확보

8.2 유의점

  • TestServer의 DB 서버 소켓 경로는 Windows 전용 (#ifdef _WIN32)
  • TestDBServer 기본 경로는 현재 DB 주입 없음 -> 영구 DB 저장은 비활성(log-only)
  • TestDBServer 기본 포트(코드 기본 8001)와 실행 스크립트 포트(문서/스크립트에서 8002 사용 가능) 혼동 위험

9. 개선 제안

  1. TestDBServer에도 설정 기반 DB 주입(SetDatabase) 경로를 main 옵션으로 연결
  2. TestServer의 DB 서버 연결 경로를 플랫폼 공통 소켓/AsyncIO 경로로 통합
  3. 운영 문서에 "기본 실행 경로(TestDBServer) vs 실험 경로(DBServer.cpp)"를 명시 (DBServer.cpp 제거 완료)
  4. 포트 기본값(8001/8002) 정책을 코드/스크립트/문서에서 단일화

10. 부록: 주요 참조 파일

  • Server/ServerEngine/Network/Core/BaseNetworkEngine.cpp
  • Server/ServerEngine/Network/Core/Session.cpp
  • Server/ServerEngine/Network/Platforms/WindowsNetworkEngine.cpp
  • Server/ServerEngine/Network/Platforms/LinuxNetworkEngine.cpp
  • Server/TestServer/src/TestServer.cpp
  • Server/TestServer/src/ClientSession.cpp
  • Server/TestServer/src/DBTaskQueue.cpp
  • Server/TestServer/src/ClientPacketHandler.cpp
  • Server/DBServer/src/TestDBServer.cpp
  • Server/DBServer/src/ServerPacketHandler.cpp
  • Server/DBServer/src/OrderedTaskQueue.cpp
  • Server/DBServer/src/ServerLatencyManager.cpp