1. UE5 멀티플레이어 구조 기초
1.1 서버–클라이언트 모델과 Authority
서버 권한(Server-Authoritative) 구조
- 언리얼 엔진의 멀티플레이어는 서버–클라이언트 모델을 기본으로 합니다.
- 서버에 있는 액터가 “진짜” 상태(Authority)를 유지하며, 클라이언트에서는 그 복제본을 표시(Proxy)합니다.
- 중요한 게임 상태(예: 체력, 아이템 획득 등)는 항상 서버가 갱신하고, 클라이언트는 이를 수신해 동기화합니다.
Authority 개념
- 서버에 있는 액터 인스턴스는
Role == ROLE_Authority로 표시되어 해당 액터의 ‘진짜’ 상태를 관리합니다. - 클라이언트에 있는 동일 액터는
ROLE_AutonomousProxy또는ROLE_SimulatedProxy가 되며, 서버의 상태를 모사·표시하는 역할입니다. - 이 방식을 통해 클라이언트 부정행위(치트) 방지, 동시 수정 충돌 방지가 가능하며, 안정적인 멀티플레이 동작이 보장됩니다.
- 서버에 있는 액터 인스턴스는
Switch Has Authority (Blueprint)
- 블루프린트에서 권한을 분기할 때는
Switch Has Authority노드를 사용합니다. Authority분기(서버)에서만 중요한 값(Health 등)을 수정하고,Remote분기(클라이언트)에서는 이펙트나 UI 업데이트만 담당하는 식으로 코드 구조를 분리합니다.
2. 리플리케이션(Replication) 설정
2.1 액터(Actor) 리플리케이션
액터의 Replicates 옵션
bReplicates = true(C++) 또는 블루프린트Details → Replication → Replicates체크로 설정합니다.- 서버에서 스폰된 액터가 클라이언트에 공유되려면 반드시
Replicates가 켜져 있어야 합니다. - Replicate Movement 항목을 추가로 체크하면 이동/회전 정보도 자동 복제됩니다.
클라이언트 스폰 vs 서버 스폰
- 일반적으로 클라이언트가 직접 스폰한 액터는 그 클라이언트에만 존재하고, 서버가 인식하지 못합니다.
- 모든 클라이언트에 액터를 보여주려면 서버가 해당 액터를 SpawnActor해줘야 합니다.
2.2 변수(Variable) 리플리케이션
Replicated 변수
- 서버에서 값이 바뀌면 자동으로 클라이언트에 동기화됩니다(단방향: 서버 → 클라이언트).
- C++:
UPROPERTY(Replicated)선언 +GetLifetimeReplicatedProps에서DOREPLIFETIME등록 - 블루프린트: 변수
Details에서Replicated또는RepNotify체크
RepNotify (ReplicatedUsing)
- 값이 변경될 때 서버·클라이언트 양쪽에서 자동 호출되는 통지 함수를 설정할 수 있습니다.
- 블루프린트:
OnRep_VariableName이벤트 노드 - C++:
UPROPERTY(ReplicatedUsing=OnRep_Func)선언 후 해당 함수 구현 - 클라이언트에서 온 값이 도착할 때 후속 로직(이펙트, UI 갱신)을 수행함으로써 이벤트 복제보다 효율적으로 상태 변화를 처리할 수 있습니다.
2.3 함수(RPC) 리플리케이션
원격 함수 호출(Remote Procedure Call, RPC)
- 특정 함수(이벤트)를 호출하면, 네트워크를 통해 서버나 클라이언트에서 실행하게 하는 방식입니다.
- 블루프린트: 커스텀 이벤트 →
Replication항목 설정 - C++:
UFUNCTION(Server/Client/NetMulticast, Reliable/Unreliable)선언
RPC 유형
- Server RPC (Run on Server)
- 클라이언트가 함수를 호출하면 서버에서 실행. 주로 “서버에게 무언가를 요청”할 때 사용.
- 호출할 액터를 소유(Owner)한 클라이언트만 유효하게 호출할 수 있습니다.
- Client RPC (Run on Owning Client)
- 서버에서 특정 액터 소유 클라이언트에게 함수를 호출하여, 해당 클라이언트에서만 실행.
- 예: 플레이어 인벤토리나 UI 업데이트를 해당 플레이어에게만 보낼 때.
- Multicast RPC (NetMulticast)
- 서버가 함수를 호출하면 자기 자신 포함 모든 클라이언트의 해당 액터에서 실행.
- 폭발 이펙트나 라운드 시작 알림 등 “모두에게 동시에 보여줄 이벤트”에 사용.
- 단, 액터가 각 클라이언트에 존재하지 않으면 전송되지 않습니다.
- Server RPC (Run on Server)
신뢰성(Reliability)
Reliable: 반드시 전송 및 순서 보장을 하지만, 너무 많이 쓰면 지연이 커질 수 있음.Unreliable: 패킷 유실 시 재전송 보장 없음. 대량·빈번한 이벤트는Unreliable권장.- 가능하면 상태 동기화는 변수 복제에 맡기고, RPC는 트리거 용도로만 쓰는 것이 좋습니다.
3. Net Role과 Net Dormancy
3.1 Net Role(네트워크 역할)
Role == ROLE_Authority- 서버에서 실행되고 있음을 의미(권한 보유). 모든 액터는 서버에서 Authority를 갖습니다.
ROLE_AutonomousProxy- 클라이언트에 있으면서 해당 액터를 소유(조종) 중인 경우. 플레이어 본인의 캐릭터 등.
- 클라이언트 → 서버 RPC를 보낼 수 있는 주체.
ROLE_SimulatedProxy- 클라이언트에 있지만 소유하지 않는 액터(타 플레이어 캐릭터 등).
- 서버 상태를 단순히 시뮬레이션·표시만 할 뿐, 직접 수정 권한은 없습니다.
이런 역할을 파악하면 “어떤 코드가 서버에서만 동작해야 하는지”, “어떤 코드는 클라이언트 전용인지”를 명확히 구분할 수 있습니다.
3.2 Net Dormancy(네트워크 휴면)
변화가 없는 액터에 대해 복제(Replication)를 일시 중단해 서버·네트워크 부하를 줄이는 기법.
AActor::NetDormancy로 설정하며, 주요 모드는 다음과 같습니다:모드 설명 DORM_Awake 기본 상태(깨어 있음). 매 틱마다 복제 후보로 검사합니다. Dormant 상태로 전환 가능. DORM_DormantAll 모든 연결에 대해 휴면(더 이상 복제 안 함). 서버가 깨우기 전까지는 동기화가 중단됩니다. DORM_DormantPartial 일부 연결에만 Dormant 적용. 고급 설정(Replication Graph 등)에서 사용됩니다. DORM_Initial 레벨 시작 시부터 Dormant. 초기 복제도 생략하여 네트워크 부하를 줄일 수 있습니다. Dormant 상태를 해제(
FlushNetDormancy)하면, 누적된 변수 변화가 한꺼번에 전송됩니다.- 너무 많은 액터가 동시에 깨나지 않도록 주의해야 하며, “변경이 드문 객체”에 효율적으로 적용하면 성능 이점을 얻습니다.
4. 최적화 기법
4.1 대역폭 및 성능 절약
- 중복 데이터 전송 줄이기
- 클라이언트에서 예측·계산 가능한 값은 굳이 서버가 매 프레임 보내지 않아도 됩니다(예: 풍차 날개 회전 각도).
- 큰 데이터 전송 최소화
- 대용량 배열 등은
Fast TArray Replication(부분 복제)이나 압축 직렬화 등을 활용해 최적화합니다.
- 대용량 배열 등은
- 엔진 제공 이동 컴포넌트 활용
CharacterMovementComponent나ProjectileMovementComponent는 이미 예측·보정 로직을 갖추고 있음.- 위치·회전을 직접 RPC로 보낼 필요 없이, 엔진 기능에 맡기는 편이 낫습니다.
- Reliable RPC 남용 금지
- 반드시 순서 보장이 필요한 중요한 이벤트(예: 매치 종료) 외에는 가능하면
Unreliable을 사용. - 과도한
Reliable은 패킷 대기열을 증가시켜 지연을 유발할 수 있습니다.
- 반드시 순서 보장이 필요한 중요한 이벤트(예: 매치 종료) 외에는 가능하면
4.2 리플리케이션 조건 및 빈도 조절
변수 복제 조건(Replication Condition)
- C++:
DOREPLIFETIME_CONDITION으로COND_OwnerOnly,COND_SkipOwner,COND_InitialOnly등 지정 가능. - 필요 없는 클라이언트에게는 아예 값을 보내지 않도록 설계해 대역폭을 절감할 수 있습니다.
- C++:
NetUpdateFrequency
- 액터별로 초당 최대 업데이트 빈도를 조정 가능.
- 움직임이 거의 없는 오브젝트는 낮게(예: 5~10), 중요 캐릭터는 기본값(100) 유지 등 상황에 따라 튜닝합니다.
Relevancy(관련성) 설정
- Net Cull Distance로 일정 거리 밖 클라이언트에는 복제를 하지 않음.
Always Relevant,Only Relevant to Owner등 옵션으로 모든 클라이언트에 항상 보내거나, 소유자에게만 보내도록 제어.- IsNetRelevantFor 함수를 오버라이드하거나 Replication Graph를 활용해 거리 이외 조건(팀, 시야 등)으로도 세분화 가능합니다.
5. 실전 예제: 플레이어 캐릭터 체력 동기화
5.1 시나리오 개요
- 플레이어가 상대를 공격하면 상대 캐릭터 체력이 줄고, 모든 클라이언트에 체력값이 동기화되어 UI에 반영된다고 가정.
5.2 구현 흐름
캐릭터 액터 설정
bReplicates = true로 캐릭터 복제를 활성화.Health변수를UPROPERTY(ReplicatedUsing=OnRep_Health)로 선언(C++ 기준).
서버 RPC: 체력 감소 함수
ServerTakeDamage(float Damage)함수를UFUNCTION(Server, Reliable)로 선언.- 클라이언트에서 호출 → 서버에서 실제 체력 감소 로직 실행.
RepNotify: OnRep_Health
- 서버에서
Health가 바뀌면 클라이언트에 복제됨. - 클라이언트의
OnRep_Health가 호출돼 UI 업데이트 및 이펙트 처리.
- 서버에서
공격 입력
- 총알이 맞았을 때 또는 공격 판정 시,
OtherPlayer->ServerTakeDamage(DamageAmount)를 호출. - 서버는
Health -= DamageAmount후 0 이하이면 사망 처리. - 변경된
Health가 자동 복제되며, 모든 클라이언트가 체력 변화를 인지.
- 총알이 맞았을 때 또는 공격 판정 시,
5.3 예시 코드(C++)
// PlayerCharacter.h (요약)
UCLASS()
class APlayerCharacter : public ACharacter
{
GENERATED_BODY()
public:
UPROPERTY(ReplicatedUsing=OnRep_Health)
float Health;
UFUNCTION()
void OnRep_Health();
UFUNCTION(Server, Reliable)
void ServerTakeDamage(float DamageAmount);
protected:
virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const override;
};
// PlayerCharacter.cpp (요약)
void APlayerCharacter::GetLifetimeReplicatedProps(TArray< FLifetimeProperty >& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(APlayerCharacter, Health);
}
void APlayerCharacter::OnRep_Health()
{
// 클라이언트에서 체력이 변경될 때 UI 업데이트
UpdateHealthUI(Health);
if (Health <= 0.f)
{
PlayDeathAnimation();
}
}
void APlayerCharacter::ServerTakeDamage(float DamageAmount)
{
if (!HasAuthority())
return;
Health -= DamageAmount;
if (Health <= 0.f)
{
Health = 0.f;
Die(); // 사망 처리
}
}
- 블루프린트에서도 구조는 동일하며, RepNotify와 Server/Client/MultiCast 이벤트 옵션을 활용해 비슷하게 구현할 수 있습니다.
6. 디버깅 & 문제 해결
6.1 자주 발생하는 이슈
액터가 클라이언트에 생성되지 않음
bReplicates설정 누락, 클라이언트 측 스폰(서버 미인식), 거리 Relevancy 미충족 등의 원인을 확인합니다.
변수가 동기화되지 않음
- 액터에
bReplicates = true가 켜져 있는지, 변수에Replicated(또는RepNotify)가 설정되었는지 확인. - 값 변경이 서버에서만 일어나는지(클라이언트 측 수정은 서버로 RPC 요청해야 함).
- 액터에
RPC가 호출되지 않음
- Server RPC → 반드시 액터를 소유한 클라이언트만 호출 가능. 소유권이 없는 곳에서 부르면 무시됨.
- Multicast → 액터가 해당 클라이언트에 존재해야 전달됨(PlayerController 등은 대부분 자기 소유 클라에만 있음).
지터(jitter), 위치 불일치
- 클라이언트 예측과 서버 권한이 어긋나면 보정 과정에서 순간 이동이 보일 수 있음.
CharacterMovementComponent의 스무딩·보간 설정 확인, 네트워크 품질(핑/손실) 시뮬레이션을 통해 개선 가능.
6.2 UE5 네트워크 디버깅 도구
- stat net
- 네트워크 전송량(패킷/바이트), 지연, 채널 등 실시간 통계 확인.
- 네트워크 지연/손실 시뮬레이션
- 콘솔 명령어
Net PktLag=100,Net PktLoss=10등을 통해 인위적 랙·패킷 손실 테스트.
- 콘솔 명령어
- 로그(LogNet 등)
- RPC나 RepNotify 실행 로그를 자세히 출력해 디버깅. (대규모 프로젝트에서 주의)
- Network Profiler / Unreal Insights
netprofile명령으로 기록 후.nprof파일을 NetworkProfiler.exe로 열어 프레임별 트래픽, RPC별 사용량 등을 분석.- Unreal Insights의 Networking Insights 플러그인을 통해 패킷 단위 타임라인 분석 가능(고급).
7. 추가 정보 & 고급 주제
7.1 UE5 최신 네트워크 기능 (Iris 등)
- Iris Replication System
- UE5에서 실험적(Experimental)으로 도입된 차세대 복제 시스템.
- 대규모 플레이어/액터를 더 효율적으로 동기화하기 위해 설계되었으며, 향후 Replication Graph를 대체할 가능성이 큼.
7.2 GAS(Gameplay Ability System)와 리플리케이션
- Gameplay Ability System(GAS)
- 능력(Ability)·버프/디버프(Effect) 등을 서버 권한으로 처리하며, 내부에서 자동 리플리케이션 가능.
AbilitySystemComponent::SetReplicationMode를 통해 Full/Mixed/Minimal로 복제 정보 범위를 제어 가능.- 대규모 효과나 세밀한 스택 정보를 모두 보낼 필요 없는 경우, Minimal 모드로 트래픽 절감 가능.
7.3 일반적인 멀티플레이 팁
- 서버 권위 모델 유지
- 서버만이 중요한 게임 상태를 변경하도록 하고, 클라이언트는 요청·입력·시각화에만 집중.
- 엔진 기능 적극 활용
- 기본 제공 컴포넌트(CharacterMovement 등) + Relevancy, Dormancy, RPC 설정 등을 잘 조합하면 안정적·효율적 동기화 달성.
- 지속적 테스트
- 에디터에서 다중 클라이언트 실행 &
Dedicated Server설정 후 테스트, 실제 네트워크 환경(핑/손실)도 모의 실험.
- 에디터에서 다중 클라이언트 실행 &
- 성능 측정 습관
- 정기적으로 stat net, Network Profiler 등을 체크해 문제 지점을 조기에 파악·개선.
마무리
언리얼 엔진 5의 네트워크 시스템은 서버–클라이언트 구조와 Authority(권한) 원칙을 근간으로 합니다. 액터와 변수, 함수를 복제(Replication)하며, Dormancy와 Relevancy 등 최적화 기능을 적절히 활용해 필요한 데이터만 전송하도록 설계해야 합니다.
- 핵심 요약
- 서버는 “진짜” 게임 상태를 유지하고, 클라이언트는 이를 복제해 표시한다.
- 변수는
Replicate옵션으로 서버→클라이언트 동기화, 함수는 RPC로 상호 요청·실행. - Dormancy, NetUpdateFrequency, Relevancy 등을 통해 대역폭·CPU 사용량을 제어한다.
- Network Profiler, stat net, RPC 로깅 등으로 트래픽·동기화를 꾸준히 모니터링한다.
이와 같은 원리를 숙지하고 구현에 반영하면, 안정적이고 공정한 멀티플레이 환경을 구성할 수 있습니다. 행운을 빕니다!
참고 자료(Reference)
- Replication | Unreal Engine Community Wiki
- A Crash Course in Blueprint Replication - Unreal Engine
- Replication | An Unreal Engine Blog by Cedric Neukirchen
- Problems with replication in UE5 - Epic Developer Community Forums
- Role_Authority explanation needed. - Epic Developer Community Forums
- need some clarification on how dormancy really works - Epic Developer Community Forums
- Actor Replication Config | 虚幻社区知识库
- Unreal Engine Multiplayer Tips and Tricks - WizardCell
- Iris FAQ | Epic Developer Community
Note: 본 문서는 공개적으로 검증 가능한 언리얼 엔진 공식 문서와 커뮤니티 자료를 참조하여 작성했습니다. 구현 시점, 엔진 버전에 따라 일부 세부 동작이 달라질 수 있으므로, 실제 프로젝트에 적용하기 전 반드시 공식 문서 및 엔진 릴리스 노트를 확인하시기 바랍니다.
'UnraealEngine' 카테고리의 다른 글
| Data Asset vs Primary Data Asset (1) | 2025.03.26 |
|---|---|
| 저장 시스템 (0) | 2025.03.14 |
| 언리얼 엔진 5에서 스팀 OSS 기능 구현 가이드 (0) | 2025.03.13 |
| 언리얼 엔진 5 멀티플레이어 가이드: 세션 관리 & Net Role/Authority 심층 (0) | 2025.03.13 |
| UE5 C++ 멀티플레이어: RPC & 리플리케이션 심층 가이드 (0) | 2025.03.13 |