네트워킹 아키텍처 개요
Server-Authoritative 모델, NetDriver, NetConnection 구조 이해
Server-Authoritative 모델
UE5 네트워킹의 핵심 철학
Unreal Engine의 네트워킹은 서버 권위(Server-Authoritative) 모델을 기반으로 합니다. 서버가 게임 상태의 진실(Truth)을 보유하고, 클라이언트는 서버의 결정을 따릅니다.
왜 서버 권위인가?
- 치트 방지 - 클라이언트는 자신의 상태를 직접 변경할 수 없음
- 일관성 보장 - 모든 클라이언트가 동일한 게임 상태를 공유
- 충돌 해결 - 동시 액션 발생 시 서버가 최종 판정
// 서버 권위 체크 패턴
void AMyCharacter::TakeDamage(float Damage)
{
// 서버에서만 실제 데미지 처리
if (HasAuthority())
{
Health -= Damage;
// Health는 Replicated이므로 클라이언트에 자동 전파
if (Health <= 0)
{
Die();
}
}
}
NetDriver와 Connection 구조
네트워크 통신의 기반 클래스
NetDriver 개요
NetDriver는 Unreal Engine 네트워킹의 핵심 클래스로, 소켓 통신과 연결 관리를 담당합니다.
서버 NetDriver
연결된 모든 플레이어에 대한 NetConnection 목록을 유지합니다.
클라이언트 NetDriver
서버에 대한 단일 NetConnection만 보유합니다.
// NetDriver 설정
[/Script/OnlineSubsystemUtils.IpNetDriver]
NetConnectionClassName="/Script/OnlineSubsystemUtils.IpConnection"
MaxClientRate=15000
MaxInternetClientRate=10000
서버 초기화 흐름
// UIpNetDriver::InitListen 에서 시작
// FURL 클래스로 IP, 포트, 프로토콜 설정
// 기본 포트: 7777 (UDP)
bool UIpNetDriver::InitListen(
FNetworkNotify* InNotify,
FURL& LocalURL,
bool bReuseAddressAndPort,
FString& Error)
{
// 1. 소켓 생성 및 바인딩
// 2. 리스닝 시작
// 3. NetConnection 대기
return true;
}
Packet과 Bunch 구조
네트워크 데이터 전송 단위
[Packet]
+-- Header (메타데이터, ACK 정보)
+-- Bunch 1
| +-- Channel ID
| +-- Sequence Number
| +-- Data (Property Changes / RPC)
+-- Bunch 2
| +-- ...
+-- Footer
| 용어 | 설명 | 제한 |
|---|---|---|
| Packet | NetConnection 쌍 간에 전송되는 데이터 블록 | MTU (보통 1200-1500 bytes) |
| Bunch | Channel 쌍 간에 전송되는 데이터 블록 | 최대 64KB |
| Partial Bunch | 64KB 초과 시 분할 전송되는 Bunch | 자동 분할/조립 |
64KB를 초과하는 데이터를 한 번에 복제하면 Partial Bunch로 분할됩니다. 이는 네트워크 지연과 패킷 손실 위험을 증가시킵니다. 대용량 데이터는 청크로 나누어 전송하세요.
네트워크 역할
ENetRole과 ENetMode 이해
ENetRole
enum ENetRole
{
ROLE_None, // 복제되지 않는 Actor
ROLE_SimulatedProxy, // 다른 클라이언트에서 시뮬레이션
ROLE_AutonomousProxy, // 로컬 플레이어가 제어 (예측 가능)
ROLE_Authority // 서버에서 권위를 가짐
};
Authority
서버에서 모든 Actor의 기본 역할. 게임 로직의 진실을 보유합니다.
Autonomous Proxy
소유 클라이언트에서 자신의 Pawn. 입력 예측이 가능합니다.
Simulated Proxy
다른 플레이어의 Pawn. 서버 데이터를 보간하여 표시합니다.
ENetMode
enum ENetMode
{
NM_Standalone, // 싱글플레이어
NM_DedicatedServer, // 헤드리스 서버
NM_ListenServer, // 호스트 + 서버
NM_Client // 원격 클라이언트
};
// 사용 예
if (GetNetMode() == NM_DedicatedServer)
{
// 전용 서버 전용 로직
}
핵심 요약
- Server-Authoritative - 서버가 게임 상태의 유일한 진실, 클라이언트는 서버 결정을 따름
- NetDriver - 소켓 통신 관리, 서버는 다수의 NetConnection, 클라이언트는 단일 NetConnection
- Packet/Bunch - Packet은 네트워크 전송 단위, Bunch는 채널 데이터 단위 (최대 64KB)
- NetRole - Authority(서버), AutonomousProxy(소유자), SimulatedProxy(관찰자)
- HasAuthority() - 서버에서만 true를 반환, 게임 로직 분기의 핵심
도전 과제
배운 내용을 직접 실습해보세요
ACharacter를 상속한 클래스에서 TakeDamage 함수를 구현하고, HasAuthority()로 서버에서만 Health를 감소시키세요. Health를 UPROPERTY(Replicated)로 선언하여 클라이언트에 자동 전파되는지 확인하세요.
GetNetMode()를 사용하여 NM_DedicatedServer, NM_ListenServer, NM_Client 각각에서 다른 로그를 출력하는 함수를 작성하세요. PIE에서 서버 1개 + 클라이언트 2개로 테스트하세요.
GetLocalRole()과 GetRemoteRole()을 사용하여 Authority, AutonomousProxy, SimulatedProxy 각 역할에서 서로 다른 UI를 표시하는 캐릭터 정보 위젯을 구현하세요. 자신의 캐릭터에만 체력바 숫자를 표시하고, 다른 플레이어에겐 바만 보이도록 하세요.