PART 8 - 강의 1/2
Server Authority 패턴
서버 권한 모델과 치트 방지 설계
01
권한 모델 비교
Server vs Client Authority
권한 모델
┌─────────────────────────────────────────────────────────────┐
│ 권한 모델 비교 │
├─────────────────────────────────────────────────────────────┤
│ │
│ [Server Authority] (권장) │
│ - 서버가 모든 게임 상태의 진실 │
│ - 클라이언트는 입력만 전송 │
│ - 서버가 검증 후 결과 복제 │
│ 장점: 치트 방지, 일관성 │
│ 단점: 지연 시간 체감 │
│ │
│ [Client Authority] │
│ - 클라이언트가 자신의 상태 결정 │
│ - 서버는 결과만 전달 │
│ 장점: 즉각적 반응 │
│ 단점: 치트 취약 │
│ │
│ [Hybrid] (UE5 기본) │
│ - 이동: Client Prediction + Server Reconciliation │
│ - 중요 액션: Server Authority │
│ │
└─────────────────────────────────────────────────────────────┘
UE5 기본 모델
UE5는 Server-Authoritative 모델을 기본으로 합니다. HasAuthority()가 true인 Actor(서버)만 게임 상태를 변경할 수 있습니다.
02
Server Authority 구현
중요 로직의 서버 처리
C++
// 데미지 처리 - 서버에서만
void AMyCharacter::TakeDamage(float Damage, ...)
{
// 클라이언트에서 호출되면 서버로 RPC
if (!HasAuthority())
{
// 클라이언트는 데미지 적용 불가
return;
}
// 서버에서만 HP 감소
CurrentHealth = FMath::Max(0.f, CurrentHealth - Damage);
// HP는 복제되어 클라이언트에 전달
if (CurrentHealth <= 0.f)
{
ServerDie();
}
}
// 아이템 획득 - 서버 검증
void AMyCharacter::RequestPickupItem(AMyItem* Item)
{
if (IsLocallyControlled())
{
// 클라이언트: 서버에 요청
ServerPickupItem(Item);
}
}
UFUNCTION(Server, Reliable, WithValidation)
void AMyCharacter::ServerPickupItem(AMyItem* Item);
bool AMyCharacter::ServerPickupItem_Validate(AMyItem* Item)
{
// 기본 유효성 검사
return Item != nullptr;
}
void AMyCharacter::ServerPickupItem_Implementation(AMyItem* Item)
{
// 서버에서 거리 검증
float Distance = FVector::Dist(
GetActorLocation(),
Item->GetActorLocation());
if (Distance > MaxPickupDistance)
{
UE_LOG(LogNet, Warning,
TEXT("Pickup rejected: too far (%.1f)"), Distance);
return;
}
// 아이템이 이미 획득되었는지 확인
if (Item->bPickedUp)
{
return;
}
// 서버에서 아이템 획득 처리
Item->bPickedUp = true;
Inventory.Add(Item->ItemData);
Item->Destroy();
}
03
RPC 검증 패턴
WithValidation 활용
C++
// 스킬 사용 RPC 검증
UFUNCTION(Server, Reliable, WithValidation)
void ServerUseAbility(int32 AbilityIndex, FVector TargetLocation);
bool AMyCharacter::ServerUseAbility_Validate(
int32 AbilityIndex,
FVector TargetLocation)
{
// 1. 인덱스 범위 검증
if (AbilityIndex < 0 || AbilityIndex >= Abilities.Num())
{
return false; // 연결 끊김!
}
// 2. 타겟 위치 합리성 검증
float MaxRange = Abilities[AbilityIndex].MaxRange;
if (FVector::Dist(GetActorLocation(), TargetLocation) > MaxRange * 1.5f)
{
return false; // 명백한 치트
}
return true;
}
void AMyCharacter::ServerUseAbility_Implementation(
int32 AbilityIndex,
FVector TargetLocation)
{
// Implementation에서 추가 검증 (연결 끊지 않음)
// 쿨다운 체크
if (!Abilities[AbilityIndex].IsReady())
{
UE_LOG(LogNet, Warning, TEXT("Ability on cooldown"));
return; // 무시만 함
}
// 마나/리소스 체크
if (CurrentMana < Abilities[AbilityIndex].ManaCost)
{
return;
}
// 시야 체크 (월핵 방지)
if (!HasLineOfSightTo(TargetLocation))
{
return;
}
// 모든 검증 통과 - 스킬 실행
ExecuteAbility(AbilityIndex, TargetLocation);
}
Validate vs Implementation
Validate: false 반환 시 클라이언트 연결 끊김. 명백한 치트에만 사용.
Implementation: 요청 무시. 네트워크 지연으로 인한 정상적 불일치에 사용.
04
상태 복제 보안
민감 정보 보호
C++
void AMyCharacter::GetLifetimeReplicatedProps(
TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
// 모든 클라이언트에게 복제 (공개 정보)
DOREPLIFETIME(AMyCharacter, CurrentHealth);
DOREPLIFETIME(AMyCharacter, TeamId);
// 오너에게만 복제 (개인 정보)
DOREPLIFETIME_CONDITION(AMyCharacter, Inventory, COND_OwnerOnly);
DOREPLIFETIME_CONDITION(AMyCharacter, CurrentMana, COND_OwnerOnly);
DOREPLIFETIME_CONDITION(AMyCharacter, QuestProgress, COND_OwnerOnly);
// 서버 전용 (복제 안 함)
// - 다른 플레이어의 정확한 위치 (안개 속)
// - 숨겨진 아이템 정보
// - 게임 비밀 데이터
}
// 적 정보 필터링 (전장의 안개)
bool AMyCharacter::IsNetRelevantFor(
const AActor* RealViewer, ...) const
{
// 같은 팀은 항상 보임
if (IsSameTeam(RealViewer))
return true;
// 적은 시야 내에만 복제
return IsVisibleTo(RealViewer);
}
SUMMARY
핵심 요약
- Server Authority - 서버가 게임 상태의 유일한 진실
- HasAuthority() - 서버에서만 중요 로직 실행
- WithValidation - 명백한 치트 시 연결 끊기
- COND_OwnerOnly - 민감 정보는 오너에게만 복제
PRACTICE
도전 과제
배운 내용을 직접 실습해보세요
실습 1: 서버 권위 아이템 시스템
아이템 획득/사용을 Server RPC로만 처리하고, 인벤토리 상태를 서버에서 복제하는 시스템을 구현하세요. 클라이언트에서 직접 인벤토리를 수정할 수 없도록 HasAuthority() 체크를 추가하세요.
실습 2: 서버 검증 RPC 패턴
UFUNCTION(Server, Reliable, WithValidation)으로 스킬 사용 RPC를 구현하세요. Validate에서 쿨다운, 마나, 사거리를 검증하고, Implementation에서 실제 효과를 적용하세요.
심화 과제
클라이언트 예측 + 서버 권위 하이브리드 전투 시스템을 구현하세요. 클라이언트에서 즉시 이펙트를 재생하되, 서버 검증 실패 시 롤백하는 Optimistic Execution 패턴을 적용하세요.