Files
a301_mmo_game_server/MMOTestServer
2026-03-16 11:27:07 +09:00
..
2026-03-16 11:27:07 +09:00
2026-02-28 14:16:07 +09:00
2026-02-28 14:16:07 +09:00
2026-02-28 14:16:07 +09:00
2026-02-28 14:16:07 +09:00

A301 MMO Game Server - 프로젝트 보고서


1. 프로젝트 개요

항목 내용
프로젝트명 A301 MMO Game Server
언어 C# (.NET 9.0)
네트워크 LiteNetLib (UDP 기반)
직렬화 Protocol Buffers (protobuf-net)
데이터베이스 MySQL (Dapper ORM)
로깅 Serilog
배포 Docker Compose

2. 프로젝트 구현 구성

2.1 디렉토리 구조

a301_mmo_game_server/
├── MMOTestServer/
│   ├── MMOserver/                    # 게임 서버 실행 프로젝트
│   │   ├── Api/
│   │   │   └── RestApi.cs            # JWT 토큰 검증 (외부 API 호출)
│   │   ├── Game/
│   │   │   ├── GameServer.cs         # 메인 게임 서버 (ServerBase 상속)
│   │   │   ├── Player.cs             # 플레이어 엔티티 (상태 + 위치)
│   │   │   ├── Channel/
│   │   │   │   ├── Channel.cs        # 단일 게임 채널
│   │   │   │   ├── ChannelManager.cs # 채널 관리 (Singleton)
│   │   │   │   └── Maps/
│   │   │   │       └── Robby.cs      # 로비 맵
│   │   │   └── Engine/
│   │   │       └── Vector3.cs        # 3D 위치 구조체
│   │   ├── Packet/
│   │   │   ├── PacketHeader.cs       # PacketCode Enum 정의
│   │   │   └── PacketBody.cs         # 모든 패킷 클래스 (ProtoContract)
│   │   ├── RDB/                      # 데이터베이스 계층
│   │   │   ├── DbConnectionFactory.cs
│   │   │   ├── Models/
│   │   │   ├── Repositories/
│   │   │   ├── Services/
│   │   │   └── Handlers/
│   │   ├── Utils/
│   │   │   ├── Singleton.cs
│   │   │   └── UuidGeneratorManager.cs
│   │   ├── Program.cs               # 서버 진입점
│   │   └── config.json              # DB 접속 설정
│   │
│   ├── ServerLib/                    # 핵심 네트워크 라이브러리 (DLL)
│   │   ├── Service/
│   │   │   ├── ServerBase.cs         # 추상 서버 베이스 클래스
│   │   │   ├── Session.cs            # 세션 상태 관리
│   │   │   └── SessionManager.cs     # 세션 매니저
│   │   ├── Packet/
│   │   │   ├── PacketSerializer.cs   # Protobuf 직렬화 (4바이트 헤더)
│   │   │   └── PacketType.cs         # 기본 패킷 타입
│   │   ├── RDB/
│   │   │   ├── Database/
│   │   │   │   └── IDbConnectionFactory.cs
│   │   │   ├── Repositories/
│   │   │   │   └── ARepository.cs    # 제네릭 비동기 Repository 베이스
│   │   │   └── Handlers/
│   │   │       ├── HelperHandler.cs
│   │   │       └── Response.cs
│   │   └── Utils/
│   │       └── CrashDumpHandler.cs   # 크래시 덤프 핸들러
│   │
│   └── MMOserver.sln
│
├── ClientTester/                     # 클라이언트 테스트 도구
│   └── EchoClientTester/
│       ├── DummyService/             # 더미 플레이어 시뮬레이션
│       │   ├── DummyClientService.cs
│       │   ├── DummyClients.cs
│       │   └── MapBounds.cs
│       ├── EchoDummyService/         # Echo/Ping 테스트
│       │   ├── EchoDummyClientService.cs
│       │   └── EchoDummyClients.cs
│       └── Packet/
│
├── compose.yaml                      # Docker Compose (MySQL + Server)
└── ReadMe.md                         # DB 아키텍처 문서

2.2 핵심 모듈 구성

ServerLib (네트워크 코어 라이브러리)

모듈 파일 역할
ServerBase ServerBase.cs 추상 서버 - 연결/해제/패킷 수신 이벤트 처리
Session Session.cs 인증 상태 + Peer 매핑 (hashKey, token)
PacketSerializer PacketSerializer.cs 4바이트 헤더(type 2B + size 2B) + Protobuf 페이로드
ARepository ARepository.cs 제네릭 비동기 CRUD (Dapper.Contrib 기반)
CrashDumpHandler CrashDumpHandler.cs 예외 로깅 + 메모리 힙 덤프 생성

MMOserver (게임 로직)

모듈 파일 역할
GameServer GameServer.cs 패킷 라우팅 + 게임 로직 처리 (ServerBase 상속)
Player Player.cs 플레이어 데이터 (위치, HP/MP, 닉네임 등)
Channel Channel.cs 채널 단위 플레이어 그룹 관리
ChannelManager ChannelManager.cs 전역 채널 관리 (Singleton)
RestApi RestApi.cs JWT 토큰 검증 (외부 인증 API 연동)
UuidGeneratorManager UuidGeneratorManager.cs Lock-free 고유 ID 생성기

2.3 패킷 프로토콜 정의

코드 패킷명 전송 방식 설명
1 ACC_TOKEN Reliable 실제 JWT 토큰 인증
1001 DUMMY_ACC_TOKEN Reliable 더미 클라이언트 인증
1000 ECHO Reliable 네트워크 테스트 (Ping)
2 LOAD_CHANNEL Reliable 채널 목록 응답
3 INTO_CHANNEL Reliable 채널 입장
5 UPDATE_CHANNEL_USER Reliable 유저 입장/퇴장 알림
6 TRANSFORM_PLAYER Unreliable 이동/회전 동기화
7 ACTION_PLAYER Reliable 공격/스킬/회피 액션
8 STATE_PLAYER Reliable HP/MP 상태 동기화

2.4 데이터베이스 계층 (RDB)

아키텍처 패턴: Handler → Service → Repository → DB

[Handler]  API 요청 수신 / JSON 응답 반환
    ↓
[Service]  비즈니스 로직 (검증, 변환)
    ↓
[Repository]  데이터 접근 (Dapper CRUD)
    ↓
[MySQL]  커넥션 풀 (Min: 5, Max: 100)

2.5 스레드 모델

구분 방식 설명
네트워크 루프 싱글 스레드 netManager.PollEvents() 1ms 주기 호출
패킷 처리 동기 처리 Poll 루프 내에서 순차적 처리
JWT 검증 async/await HttpClient 비동기 호출
DB 연산 async/await Dapper 비동기 쿼리
UUID 생성 lock 기반 스레드 안전 ID 할당

3. 파이프라인

3.1 클라이언트 접속 ~ 게임 플레이 전체 흐름

[1] 클라이언트 접속 (UDP)
 │
 ├─ LiteNetLib ConnectionRequest
 │   └─ ServerBase.OnConnectionRequest() → 연결 키 검증
 │
 ▼
[2] 인증 (Authentication)
 │
 ├─ 클라이언트 → 서버: ACC_TOKEN 또는 DUMMY_ACC_TOKEN 패킷 전송
 │
 ├─ [실제 인증] JWT 토큰 → RestApi.VerifyTokenAsync()
 │   └─ POST https://a301.api.tolelom.xyz/api/auth/verify
 │       ├─ 성공 → username 반환, hashKey 생성
 │       ├─ 401 → 즉시 실패 (토큰 무효)
 │       └─ 기타 오류 → 3회 재시도 (1초 간격)
 │
 ├─ [더미 인증] hashKey 직접 수신 (≤1000 범위)
 │
 ├─ Session 객체 생성 (hashKey, token, peer)
 │   └─ peer.Tag에 Session 저장
 │
 ▼
[3] 채널 선택
 │
 ├─ 서버 → 클라이언트: LOAD_CHANNEL (채널 목록)
 ├─ 클라이언트 → 서버: INTO_CHANNEL (채널 선택)
 │
 ├─ 서버 처리:
 │   ├─ 채널에 플레이어 추가
 │   ├─ 기존 플레이어 목록 조회
 │   └─ 서버 → 클라이언트: INTO_CHANNEL 응답 (기존 플레이어 리스트)
 │
 ├─ 서버 → 채널 전체: UPDATE_CHANNEL_USER (새 플레이어 입장 알림)
 │
 ▼
[4] 게임 루프 (실시간 동기화)
 │
 ├─ TRANSFORM_PLAYER [Unreliable]
 │   └─ 위치(X,Y,Z) + 회전(RotY) → 채널 내 브로드캐스트
 │
 ├─ ACTION_PLAYER [ReliableOrdered]
 │   └─ 공격/스킬/회피 → 채널 내 브로드캐스트
 │
 ├─ STATE_PLAYER [ReliableOrdered]
 │   └─ HP/MP 상태 변경 → 채널 내 브로드캐스트
 │
 ▼
[5] 연결 종료
 │
 ├─ 클라이언트 → 서버: EXIT_CHANNEL
 ├─ 서버: 채널에서 플레이어 제거
 ├─ 서버 → 채널 전체: UPDATE_CHANNEL_USER (퇴장 알림)
 └─ 세션 정리 및 Peer 해제

3.2 패킷 처리 파이프라인

수신 (OnNetworkReceive)
   ↓
┌─────────────────────────────────────┐
│  4바이트 헤더 파싱                    │
│  ├─ type: ushort (2B) → 패킷 종류   │
│  └─ size: ushort (2B) → 페이로드 크기 │
└─────────────────────────────────────┘
   ↓
┌─────────────────────────────────────┐
│  Protobuf 역직렬화                    │
│  └─ byte[] → 패킷 객체              │
└─────────────────────────────────────┘
   ↓
┌─────────────────────────────────────┐
│  타입별 분기                          │
│  ├─ ECHO (1000) → HandleEcho()     │
│  ├─ AUTH (1/1001) → HandleAuth()   │
│  └─ GAME (2~8) → HandlePacket()   │
└─────────────────────────────────────┘
   ↓
┌─────────────────────────────────────┐
│  게임 로직 처리                       │
│  └─ 채널 내 브로드캐스트               │
└─────────────────────────────────────┘
   ↓
송신 (SendTo / BroadcastToChannel)

3.3 세션 관리 파이프라인

PendingPeers (미인증)           Sessions (인증 완료)
Dictionary<int, NetPeer>       Dictionary<long, NetPeer>

  접속 시 등록 ──────────────→  인증 성공 시 이동
  (peerId 기반)                 (hashKey 기반)

                               TokenHash (토큰 매핑)
                               Dictionary<string, long>
                               token → hashKey 조회
  • 재접속 처리: 동일 hashKey로 재접속 시 기존 Peer 강제 해제 → 새 Peer로 교체
  • 채널 유지: 재접속 시 기존 채널 멤버십 유지 (채널 선택 스킵)

3.4 빌드 및 배포 파이프라인

소스 코드
   ↓
dotnet build (MMOserver.sln)
   ├─ ServerLib.csproj → ServerLib.dll
   └─ MMOserver.csproj → MMOserver.exe
   ↓
Docker Build (Dockerfile)
   ↓
Docker Compose (compose.yaml)
   ├─ MySQL 컨테이너
   └─ MMOServer 컨테이너
       └─ UDP 포트: 9050, 9500

4. 버그 및 잠재적 이슈

코드 정적 분석을 통해 발견된 버그 및 잠재적 문제점 목록입니다.

4.1 버그 목록

[B1] Engine Vector3 타입 불일치 (HIGH)

  • 파일: MMOserver/Game/Engine/Vector3.cs vs MMOserver/Packet/PacketBody.cs
  • 문제: 두 Vector3 클래스가 다른 타입으로 정의됨
    • Engine/Vector3.cs: 좌표가 int 타입
    • Packet/PacketBody.cs (PacketVector3): 좌표가 float 타입
  • 영향: 실제 코드에서는 Packet Vector3만 사용되고 Engine Vector3는 사용되지 않음. 향후 Engine Vector3를 사용하는 코드가 생기면 타입 캐스팅 오류 발생
  • 권장 조치: Engine Vector3 제거 또는 float 기반으로 통일

[B2] ChannelManager.AddUser() 스레드 안전성 문제 (MEDIUM)

  • 파일: MMOserver/Game/Channel/ChannelManager.cs
  • 문제: 비동기 인증 흐름(JWT 검증 → AddUser) 후 두 요청이 동시에 같은 userId로 connectUsers.Add()를 호출할 경우 ArgumentException 발생 가능
    public void AddUser(int channelId, long userId, Player player)
    {
        connectUsers.Add(userId, channelId);  // 중복 키 시 예외 발생
        channels[channelId].AddUser(userId, player);
    }
    
  • 영향: 동시 재접속 시나리오에서 서버 크래시 가능성
  • 권장 조치: TryAdd() 사용 또는 lock 추가

[B3] PlayerId 정수 오버플로우로 인한 중복 ID (LOW)

  • 파일: MMOserver/Game/GameServer.cs
  • 문제: PlayerId = (int)(hashKey & 0x7FFFFFFF) 계산으로 서로 다른 hashKey가 동일한 PlayerId를 생성할 수 있음
    • 예: hashKey=1 → PlayerId=1, hashKey=2147483649 → PlayerId=1 (동일)
  • 영향: ID 기반 플레이어 조회 오작동
  • 권장 조치: PlayerId로 hashKey 원본(long) 사용

[B4] TokenHash 딕셔너리 무한 증가 (MEDIUM)

  • 파일: ServerLib/Service/ServerBase.cs
  • 문제: 토큰 만료 또는 로그아웃 시 tokenHash 딕셔너리에서 항목이 제거되지 않음. 장기 운영 시 모든 누적 토큰이 메모리에 남음
  • 영향: 장기 운영 서버에서 메모리 누수 (ex. 100만 로그인 이후 100만 항목 유지)
  • 권장 조치: 로그아웃/연결 해제 시 tokenHash.Remove() 호출, 또는 TTL 기반 만료 캐시 도입

[B5] 패킷 역직렬화 크기 검증 없음 (MEDIUM)

  • 파일: ServerLib/Service/ServerBase.cs
  • 문제: 패킷 페이로드가 null인지는 확인하지만, 역직렬화된 객체의 필드 크기는 검증하지 않음
  • 영향: 악의적으로 구성된 패킷(예: PlayerInfo 리스트 내 수만 개의 항목)이 메모리 과소비 유발 가능
  • 권장 조치: 역직렬화 전 페이로드 바이트 크기 상한 검증 추가

[B6] Echo 패킷에 레이트 리미팅 미적용 (MEDIUM)

  • 파일: MMOserver/Game/GameServer.cs
  • 문제: Echo 패킷 처리 경로가 세션 인증 및 레이트 리미팅 검사를 우회함
  • 영향: 인증 전 클라이언트가 Echo 패킷을 무제한으로 전송하여 서버 자원 소모 가능 (DoS)
  • 권장 조치: Echo 처리 경로에도 레이트 리미팅 적용

5. 최적화 미비점

5.1 성능 병목

[O1] BroadcastToChannel 내 반복적 딕셔너리 조회 해결됨

  • 해결: ChannelDictionary<long, NetPeer> connectPeers 추가, BroadcastToChannelGetConnectPeers()를 직접 순회하도록 변경
  • 변경 파일: Channel.cs, ChannelManager.cs, GameServer.cs
  • 효과: 100명 채널 브로드캐스트 시 sessions 딕셔너리 교차 조회 100회 → 0회 제거
  • 추가 처리: 재연결(WiFi→LTE) 시 Channel.UpdatePeer()로 peer 참조 갱신

[O2] Transform 패킷 객체 풀링 미구현

  • 파일: ServerLib/Packet/PacketSerializer.cs
  • 문제: 매 패킷마다 새 객체 생성 및 Protobuf 리플렉션 수행. Transform 패킷은 초당 수백~수천 회 발생하는 고빈도 패킷
  • 권장 조치: ObjectPool<T> 도입으로 GC 압박 감소

[O3] Dictionary 열거 시 Enumerator 힙 할당

  • 현황: 모든 열거 메서드(GetConnectUsers, GetPlayers, GetConnectPeers)를 IEnumerable<T>로 통일
  • 판단 근거: 박싱 비용(수 나노초)이 실질적으로 무시 가능한 수준이며, IEnumerable<T>가 가독성과 인터페이스 일관성 면에서 유리
  • 미적용 사유: 가독성 > 마이크로 최적화 우선

[O4] 레이트 리미터 고정 윈도우 방식

  • 파일: ServerLib/Service/Session.cs
  • 문제: 현재 고정 윈도우(Fixed Window) 방식 사용. 윈도우 경계에서 최대 2배 패킷 폭주 허용 가능
    • 예: 윈도우 끝 120개 + 새 윈도우 시작 120개 = 240개/초 순간 처리
  • 권장 조치: 슬라이딩 윈도우 또는 토큰 버킷 알고리즘으로 교체

[O5] 로깅 문자열 할당

  • 현황: 모든 패킷 처리마다 Serilog 메시지 템플릿 평가 발생
  • 권장 조치: if (Log.IsEnabled(LogEventLevel.Debug)) 가드 추가로 Debug 레벨 불필요한 평가 방지

6. 문제점 - 해결

6.1 해결된 문제

[P1] 이동 패킷 재전송 문제

  • 문제: 이동(Transform) 패킷이 ReliableOrdered로 전송되어 패킷 손실 시 재전송 발생 → 위치 동기화 지연, Head-of-Line 블로킹
  • 해결: 이동 패킷을 Unreliable 전송으로 변경 (commit: 42f0ef1)
  • 효과: 실시간성 향상, 네트워크 지연 최소화 (오래된 위치 데이터는 폐기)

[P2] 로그인 인증 실패 시 재시도 부재

  • 문제: JWT 토큰 검증 API 호출이 일시적 네트워크 오류로 실패 시 즉시 인증 실패 처리
  • 해결: 3회 재시도 로직 추가 (1초 간격), 401 응답은 즉시 실패 (commit: c8ce36a)
  • 효과: 일시적 API 장애에 대한 내결함성 확보

[P3] 토큰 → HashKey 매핑 구조

  • 문제: 토큰과 hashKey 간의 매핑이 명확하지 않아 재접속/중복 접속 처리 어려움
  • 해결: TokenHash 딕셔너리 도입, 토큰 관리 로직 구조화 (commit: bfa3394)
  • 효과: 동일 토큰 재접속 시 기존 세션 정리 및 hashKey 재활용

[P4] 에코 클라이언트 수신 버그

  • 문제: 에코 테스트 클라이언트에서 수신 패킷 처리 오류
  • 해결: 수신 로직 버그 수정 (commit: 18fd8a0)

[P5] 서버 크래시 시 디버깅 정보 부족

  • 문제: 서버 비정상 종료 시 원인 파악 불가
  • 해결: CrashDumpHandler 구현 (commit: 2be1302)
    • Debug 빌드: .log 파일 (스택 트레이스)
    • Release 빌드: .log + .dmp 파일 (힙 덤프)
    • UnhandledException, UnobservedTaskException 모두 캡처
  • 효과: 프로덕션 환경 크래시 사후 분석 가능

[P6] 패킷 레이트 리미팅 부재

  • 문제: 클라이언트의 패킷 전송 빈도 제한 없음 → 패킷 플러딩 공격에 취약
  • 해결: Session 클래스에 슬라이딩 윈도우 방식 레이트 리미터 구현
    • 초당 최대 120 패킷 허용 (MaxPacketsPerSecond)
    • 초과 시 해당 패킷 드롭 + 경고 로그
    • 3회 연속 초과 시 강제 연결 해제
    • ServerBase.OnNetworkReceive()에서 인증된 패킷 처리 전 체크
  • 적용 파일: Session.cs, ServerBase.cs
  • 효과: 악의적 패킷 플러딩 방어, 서버 안정성 향상

[P7] 부하 테스트 도구 부재

  • 문제: 대규모 동시접속 시나리오 검증 도구 없음, 기존 더미 클라이언트는 10명 고정
  • 해결: StressTest 모듈 신규 구현 (ClientTester/EchoClientTester/StressTest/)
    • StressTestClient.cs: 이동 + Echo RTT 동시 측정 클라이언트
    • StressTestService.cs: 점진적 Ramp-up, 퍼센타일 레이턴시(P50/P95/P99), CSV 내보내기
    • Program.cs: CLI 인자 지원 (stress -c 100 -d 60 --ip ...) + 대화형 모드 3번 메뉴
  • 효과: N명 동시접속 시나리오 자동 검증, 성능 병목 지점 파악

6.2 현재 남아 있는 문제

[I1] 서버 사이드 위치 검증 미구현

  • 현상: 클라이언트가 전송하는 위치를 서버에서 검증하지 않음
  • 영향: 스피드핵, 텔레포트 등 치트 방어 불가
  • 권장: MapBounds 로직을 서버 사이드에 적용, 비정상 이동 감지 시 보정

[I2] 플레이어 데이터 DB 연동 미완성

  • 현상: 플레이어 데이터가 하드코딩된 기본값 사용 (GameServer.cs 내 TODO 주석 존재)
  • 영향: 캐릭터 정보 저장/불러오기 불가, 레벨·닉네임·HP/MP 등 지속성 없음
  • 권장: Player 모델 DB 테이블 생성, 로그인 시 DB 조회

[I3] NPC / 파티 시스템 미구현

  • 현상: 패킷 코드(TRANSFORM_NPC, ACTION_NPC, UPDATE_PARTY 등)는 정의되어 있으나 핸들러 없음
  • 영향: 수신 시 경고 로그만 출력되고 무시됨
  • 권장: NPC AI 시스템, 파티 매칭 로직 순차 구현

7. 정리

7.1 아키텍처 요약

┌──────────────────────────────────────────────────────┐
│                    클라이언트 (Unity)                   │
└──────────────┬───────────────────────────┬────────────┘
               │ UDP (LiteNetLib)          │
┌──────────────▼───────────────────────────▼────────────┐
│                  ServerBase (네트워크 코어)              │
│  ┌────────────┐  ┌────────────┐  ┌─────────────────┐ │
│  │ 연결 관리    │  │ 패킷 직렬화  │  │   세션 관리      │ │
│  └────────────┘  └────────────┘  └─────────────────┘ │
└──────────────┬───────────────────────────┬────────────┘
               │                           │
┌──────────────▼───────────────┐  ┌────────▼────────────┐
│      GameServer (게임 로직)    │  │   RestApi (인증)     │
│  ┌─────────┐  ┌────────────┐ │  │  JWT 토큰 검증       │
│  │ Channel  │  │  Player    │ │  │  (외부 API 호출)     │
│  │ Manager  │  │  State     │ │  └─────────────────────┘
│  └─────────┘  └────────────┘ │
└──────────────┬───────────────┘
               │
┌──────────────▼───────────────┐
│     RDB Layer (데이터베이스)    │
│  Handler → Service → Repo    │
│         → MySQL              │
└──────────────────────────────┘

7.2 기술적 강점

항목 내용
UDP 기반 통신 LiteNetLib으로 TCP 오버헤드 없이 실시간 통신
Protobuf 직렬화 컴팩트 바이너리 인코딩으로 대역폭 절약
이동 패킷 Unreliable HOL 블로킹 방지, 최신 위치만 유효
싱글 스레드 이벤트 루프 Lock 불필요, 동시성 이슈 최소화
비동기 DB/API async/await로 네트워크 루프 블로킹 방지
크래시 덤프 프로덕션 환경 사후 분석 지원
계층화된 DB 구조 Handler-Service-Repository 패턴
Docker 배포 컨테이너화된 일관된 배포 환경

7.3 향후 작업 (Roadmap)

우선순위 작업 설명
높음 플레이어 DB 연동 캐릭터 정보 저장/불러오기 완성 (I2)
높음 버그 수정 B2 스레드 안전성, B4 메모리 누수, B6 Echo 레이트 리미팅
높음 서버 사이드 위치 검증 치트 방어를 위한 이동 유효성 검사 (I1)
중간 NPC 시스템 AI 기반 NPC 이동/전투 로직 (I3)
중간 성능 최적화 O1 브로드캐스트 최적화 (완료), O2 객체 풀링, O4 레이트 리미터 개선
낮음 파티 시스템 파티 생성/참여/매칭 (I3)
낮음 모니터링 대시보드 서버 상태/접속자 수 실시간 모니터링

완료된 항목: 패킷 레이트 리미팅 (적용 완료), 부하 테스트 도구 (구현 완료), 크래시 덤프 (적용 완료), O1 브로드캐스트 최적화 (적용 완료)

7.4 부하 테스트 도구 (StressTest)

ClientTester/EchoClientTester/StressTest/ 에 구현됨.

구성 파일

파일 역할
StressTestClient.cs 개별 스트레스 클라이언트 (이동 + Echo RTT 동시 측정)
StressTestService.cs 테스트 오케스트레이터 (Ramp-up, 통계, CSV 내보내기)

기능

기능 설명
점진적 Ramp-up N초 간격으로 클라이언트 추가 (서버 부하 단계적 증가)
지속시간 제한 테스트 자동 종료 (초 단위, 0 = 무제한)
실시간 통계 10초마다 접속수, 전송/수신 rate, AvgRTT 출력
퍼센타일 레이턴시 P50, P95, P99, Min, Max, Avg RTT 계산
최악 클라이언트 분석 RTT 상위 5명 상세 리포트
CSV 내보내기 results/stress_{N}clients_{timestamp}.csv 자동 저장

사용법

CLI 모드:

# 기본 (50명, 60초)
dotnet run -- stress

# 커스텀
dotnet run -- stress -c 100 -d 120 --ip 192.168.0.10 --port 9500

# 전체 옵션
dotnet run -- stress \
  -c 200          # 클라이언트 수
  -d 60           # 테스트 시간 (초, 0=무제한)
  -i 100          # 전송 주기 (ms)
  -r 1000         # Ramp-up 간격 (ms)
  -b 20           # Ramp-up 당 추가 수
  --ip localhost  # 서버 IP
  --port 9500     # 서버 포트

대화형 모드:

메뉴에서 3번 선택 → 클라이언트 수, 테스트 시간 입력

출력 예시

╔═══════════════════════════════════════════════╗
║           STRESS TEST 최종 리포트              ║
╠═══════════════════════════════════════════════╣
║ 테스트 시간 : 60.0초
║ 클라이언트  : 98/100 접속 유지
╠═══════════════════════════════════════════════╣
║ [처리량]
║   총 전송    : 118,200 패킷
║   총 수신    : 117,850 패킷
║   처리량     : 1,970.0 패킷/초
╠═══════════════════════════════════════════════╣
║ [레이턴시] (RTT 샘플: 59,100개)
║   Min        : 0.15 ms
║   Avg        : 1.23 ms
║   P50        : 0.89 ms
║   P95        : 3.45 ms
║   P99        : 8.12 ms
║   Max        : 25.67 ms
╚═══════════════════════════════════════════════╝

7.5 최근 개발 이력

커밋 내용
85c3276 세션 끊길 때 같은 채널에 퇴장 메시지 전송
c27e846 채널 버그 수정
d4c5a70 채널 버그 수정
ea3f64a 스트레스 테스트 기능 추가 / 패킷 처리량 제한 / 프로젝트 상황 README 추가
2be1302 크래시 덤프 기능 추가 (Release: 힙 덤프)
42f0ef1 이동 패킷 Unreliable 전송으로 변경
bfa3394 토큰 → HashKey 생성 로직 구조 변경
c8ce36a 로그인 실패 시 재시도 로직 추가
18fd8a0 에코 클라이언트 수신 버그 수정

작성일: 2026-03-06 프로젝트 상태: 핵심 네트워크 인프라 완성, 게임 콘텐츠 확장 단계

구현 완료: 네트워크 코어, 세션 관리, 채널 시스템, 인증, 레이트 리미팅, 크래시 덤프, 부하 테스트 도구 미구현: 플레이어 DB 연동, NPC/파티 시스템, 서버 사이드 위치 검증, 전투/아이템 시스템 알려진 버그: B1 Vector3 타입 불일치, B2 ChannelManager 스레드 안전성, B4 TokenHash 메모리 누수, B6 Echo DoS 취약점