언리얼 엔진 네트워크의 Role(롤) 개념 자세히 설명
언리얼 엔진의 멀티플레이 네트워크 시스템에서 **Role(롤)**과 **Remote Role(리모트 롤)**은 매우 중요한 개념입니다. Actor가 어떤 기기(서버 또는 클라이언트)에 의해 **권한(Authority)**을 가지며 상태 변경이나 RPC(Remote Procedure Call)를 수행할 수 있는지를 결정하는 정보가 바로 Role과 Remote Role입니다 ([UE5] Actor Role, Remote Role). 이 두 프로퍼티를 통해 다음과 같은 질문에 답할 수 있습니다:
- 이 액터가 네트워크 상 **복제(replication)**되고 있는가?
- 액터에 대한 **권한(authority)**은 누구에게 있는가 (서버인지, 특정 클라이언트인지)?
- 액터의 복제 방식(자율적 업데이트인지, 시뮬레이션인지)은 무엇인가?
아래에서는 **Local Role(로컬 롤)**과 **Remote Role(리모트 롤)**의 차이, 각 Role 값의 정의와 역할, 액터의 네트워크 상태에 따른 Role 할당 방식, 서버와 클라이언트 간 권한 및 복제 처리, 그리고 코드에서 Role을 활용하는 방법을 구조화하여 설명합니다.
Role vs. Remote Role: 로컬 롤과 리모트 롤의 차이
언리얼 엔진에서 Role은 해당 액터의 로컬(현재 실행 중인 로컬 머신)에서의 역할을 나타내고, Remote Role은 원격(네트워크 반대편 원격 머신)에서의 역할을 나타냅니다 (UnrealWiki: Role). 간단히 말해, Local Role은 “내가 보는 이 액터의 역할”이고 Remote Role은 “다른 피어(peer)에서 이 액터가 가지고 있는 역할”입니다 (UnrealWiki: Role). 액터가 네트워크를 통해 다른 컴퓨터로 복제되면, 서버에 있던 Role 값이 클라이언트의 Remote Role로 전달되고, 서버에 설정된 Remote Role 값이 클라이언트의 Role로 설정되는 식으로 **두 값이 교차(swap)**됩니다 (UnrealWiki: Role). 즉, 동일한 액터도 서버에서 바라본 Role/RemoteRole과 클라이언트에서 바라본 Role/RemoteRole이 서로 반대일 수 있습니다 ([UE4] Role, Remote Role).
예를 들어, 서버에서는 어떤 액터의 Role = ROLE_Authority이고 RemoteRole = ROLE_SimulatedProxy로 표시될 경우, 그 액터가 한 클라이언트에 복제되었을 때 클라이언트 측에서는 Role = ROLE_SimulatedProxy이고 RemoteRole = ROLE_Authority로 보이게 됩니다 ([UE4] Role, Remote Role). 이처럼 Role과 Remote Role은 어느 측에서 정보를 조회하느냐에 따라 달라지며, 한 쪽의 Role이 다른 쪽의 RemoteRole로 대응되는 관계입니다. 정리하면:
- Local Role(로컬 Role): 현재 이 액터를 소유한 로컬 인스턴스(서버 또는 클라이언트)에서의 역할 값입니다. 예를 들어 서버에서 보면 서버 자신의 Role이 로컬 롤이고, 클라이언트에서 보면 그 클라이언트에서의 Role이 로컬 롤입니다.
- Remote Role(원격 Role): 반대편 원격 인스턴스(상대방)의 관점에서 이 액터가 어떤 역할인지를 나타냅니다. 클라이언트에서 액터의 RemoteRole이 “Authority”라면 그 액터의 원본은 서버에서 Authority를 가짐을 의미하고, 서버에서 액터의 RemoteRole이 “AutonomousProxy”라면 해당 액터를 어떤 클라이언트가 자율적으로 제어하고 있음을 의미합니다 ([UE5] Network Role).
요약하면, Role은 자신이 속한 환경에서의 액터의 권한 상태를 나타내고, Remote Role은 네트워크 반대편에서의 액터 권한 상태를 나타냅니다 ([UE5] Network Role). 이를 통해 코드에서 현재 실행 중인 환경이 서버인지 클라이언트인지, 액터가 누구에 의해 제어되고 있는지 등을 파악할 수 있습니다. (Role == ROLE_Authority이면 해당 코드가 서버 권한으로 실행되고 있다는 의미가 됩니다.)
ENetRole 열거형과 각 Role의 정의
언리얼 엔진에서는 Actor의 Role과 RemoteRole 프로퍼티가 내부적으로 ENetRole이라는 열거형(enum)으로 정의되어 있습니다 ([UE5] Actor Role, Remote Role). 주요 Role 값과 그 의미는 다음과 같습니다. (각 Role 간의 차이를 명확히 비교하기 위해 표로 정리하였습니다.)
Role (ENetRole) 설명
| ROLE_Authority (권한) | 서버 권한을 가진 액터. 해당 액터는 서버에서 완전한 제어권을 가지며, 프로퍼티 변경을 추적하고 다른 클라이언트들에게 그 변경 사항을 **복제(replication)**하는 역할까지 수행합니다 ([UE5] Actor Role, Remote Role). 서버의 Actor는 일반적으로 ROLE_Authority이며, 이 상태에서는 RPC(멀티캐스트 등)를 송신할 수 있습니다. 한편 클라이언트에서 ROLE_Authority인 액터는 그 클라이언트에만 존재하는 로컬 액터로, 네트워크 복제를 하지 않는 경우에 나타납니다 (예: 이 액터는 해당 클라이언트에서만 존재하고 서버에는 존재하지 않음). |
| ROLE_AutonomousProxy (자율 프록시) | 자율 프록시 액터. 특정 클라이언트가 소유 및 직접 제어하는 액터입니다. 해당 클라이언트에서는 이 액터에 대해 예측(Prediction) 로직이나 사용자 입력 처리가 가능하며, 필요에 따라 서버로 RPC(예: Server 함수 호출)를 보낼 수 있습니다 ([UE5] Actor Role, Remote Role). 주로 플레이어가 조종하는 Pawn이나 Character가 이에 해당하며, 서버에서는 이러한 액터를 해당 소유 클라이언트에 대해 AutonomousProxy로 지정합니다. |
| ROLE_SimulatedProxy (시뮬레이션 프록시) | 시뮬레이션 프록시 액터. 이 액터는 **원격 시스템(서버 또는 다른 클라이언트)**에서 제어하며, 로컬 시스템에서는 해당 액터를 복제된 데이터로 시뮬레이션만 합니다 ([UE5] Actor Role, Remote Role). 다시 말해, 로컬에서는 자체적으로 상태를 변경하거나 서버로 RPC를 보낼 수 없고, 서버로부터 전송된 위치/상태 업데이트를 적용하여 모습만 동기화합니다 ([UE5] Actor Role, Remote Role). 플레이어가 직접 조종하지 않는 다른 플레이어의 캐릭터나 NPC 등이 클라이언트에서 SimulatedProxy로 동작하며, 수동적인(replicated) 객체로 취급됩니다. |
| ROLE_None (없음) | 역할 없음. 이 액터는 네트워크 복제되지 않는 경우에 해당합니다 ([UE5] Actor Role, Remote Role). Role이나 RemoteRole이 None이면 엔진이 해당 액터의 상태를 다른 피어에 전송하지 않으며, 이 액터는 현재 로컬 인스턴스에만 존재하게 됩니다. (예: 이펙트 전용 액터를 클라이언트에서만 생성한 경우, 클라이언트에서 Role=Authority이지만 RemoteRole=None으로 설정되어 다른 곳에 복제되지 않습니다.) |
위 표에서 볼 수 있듯이, **Authority(권한)**는 주로 서버가 가지는 역할이며 액터의 원본(primary) 인스턴스에 해당합니다. **AutonomousProxy(자율 프록시)**와 **SimulatedProxy(시뮬레이티드 프록시)**는 클라이언트 측 복제본에서 나타나는 역할로, 해당 액터가 클라이언트에서 직접 제어되는지 여부에 따라 구분됩니다 (Role_Authority explanation needed. - C++ - Epic Developer Community Forums) (Role_Authority explanation needed. - C++ - Epic Developer Community Forums). None은 복제되지 않음을 의미하여, 네트워크 상에 다른 대응되는 객체가 없음을 뜻합니다.
참고: 과거의 언리얼 엔진(UDK 등)에는 ROLE_DumbProxy 같은 값도 있었으나, Unreal Engine 4 이후에는 사용되지 않으며 일반적으로 위의 네 가지 역할만 사용됩니다 (UnrealWiki: Role) (Role_Authority explanation needed. - C++ - Epic Developer Community Forums).
액터의 네트워크 상태에 따른 Role 할당
Actor의 **네트워크 상태(어느 인스턴스에 존재하고 누가 소유하는지)**에 따라 Local Role과 Remote Role 값이 달라집니다. 다음은 서버와 클라이언트에서 각각 액터의 Role/RemoteRole이 어떻게 설정되는지 정리한 것입니다:
- 서버에서의 역할: 서버는 게임 세계의 권한을 가지므로, **서버에 존재하는 모든 Actor의 LocalRole은 항상 ROLE_Authority**입니다 ([Network] Network Property :: 치킨 날다). 서버가 액터를 생성(스폰)하거나 소유할 때 기본적으로 자신이 권한을 갖게 됩니다. 이 때 해당 액터가 클라이언트들에게 복제될 경우를 대비해 RemoteRole이 설정되는데:
- 만약 특정 플레이어가 소유한 액터(예: 특정 클라이언트의 Pawn/Character 등)라면, 서버에서 그 액터의 RemoteRole을 ROLE_AutonomousProxy로 지정합니다 ([Network] Network Property :: 치킨 날다). 이렇게 지정하면 해당 액터를 소유한 클라이언트에서는 이 액터를 Autonomous Proxy로 취급하게 됩니다. (언리얼 엔진 내부에서는 서버에서 SetAutonomousProxy(true)를 호출하여 클라이언트의 Pawn 등을 AutonomousProxy로 설정하는데, Pawn이 플레이어에게 **Possess(소유)**될 때 이런 처리가 자동으로 이뤄집니다 (What makes an actor Autonomous Proxy? - Multiplayer & Networking - Epic Developer Community Forums).)
- 그 외 일반 복제 Actor(어떤 특정 클라이언트의 소유가 아닌 경우)라면, 서버에서 그 액터의 RemoteRole은 ROLE_SimulatedProxy로 남습니다 ([Network] Network Property :: 치킨 날다). 즉, 해당 액터는 모든 클라이언트에서 단순히 시뮬레이션되는 복제본으로 존재하게 됩니다.
- 만약 서버에서만 존재하고 아예 클라이언트에 보내지지 않는 액터라면(RemoteRole이 None), 복제가 비활성화된 상태입니다.
- 클라이언트에서의 역할: 클라이언트에 복제되어 온 Actor들은 서버에서 설정한 RemoteRole 값에 따라 LocalRole이 결정됩니다. 서버에서 RemoteRole이 AutonomousProxy로 설정된 액터는 해당 클라이언트를 소유자로 하여 도착하므로, 그 **클라이언트의 LocalRole이 ROLE_AutonomousProxy**가 됩니다 ([Network] Network Property :: 치킨 날다). 반면 서버에서 RemoteRole이 SimulatedProxy로 설정된 액터는 **대부분의 클라이언트에서 LocalRole이 ROLE_SimulatedProxy**가 됩니다 (직접 소유하지 않는 한) ([Network] Network Property :: 치킨 날다). 요약하면:
- 클라이언트 자신이 소유한 액터: LocalRole = ROLE_AutonomousProxy (해당 클라이언트에서 직접 제어 가능) ([Network] Network Property :: 치킨 날다).
- 다른 곳(서버 또는 타 클라이언트)이 소유한 액터: LocalRole = ROLE_SimulatedProxy (해당 클라이언트에서는 읽기전용 복제본) ([Network] Network Property :: 치킨 날다).
- 이 때 RemoteRole은 복제된 액터라면 대개 ROLE_Authority로 표시됩니다 ([Network] Network Property :: 치킨 날다). 즉, 클라이언트는 모든 복제 Actor의 원본 권한이 서버에 있음을 RemoteRole을 통해 인지하게 됩니다. 이는 앞서 설명한 것처럼 서버의 Role(Auhtority)이 클라이언트에서는 RemoteRole로 보이기 때문입니다.
- 클라이언트 전용(Local) 액터: 만약 어떤 액터가 해당 클라이언트에서만 생성되고 네트워크 복제되지 않을 경우, 그 액터는 해당 클라이언트에서 LocalRole = ROLE_Authority로 간주됩니다 (자기 자신만의 권한) ([Network] Network Property :: 치킨 날다). 당연히 이 액터는 서버나 다른 클라이언트에는 없으므로 RemoteRole = ROLE_None입니다 ([Network] Network Property :: 치킨 날다).
위 내용을 그림으로 정리하면, 서버의 Actor는 항상 Authority이며 RemoteRole로 클라이언트의 역할 상태를 지정하고, 클라이언트의 Actor는 서버가 Authority임을 RemoteRole로 나타내면서 **LocalRole로 자신이 그 액터를 제어하는지 여부(Autonomous vs Simulated)**를 표시한다고 볼 수 있습니다.
서버와 클라이언트의 Authority 및 Replication 처리
네트워크 멀티플레이에서 **서버(Server)**는 기본적으로 모든 복제 Actor의 권한을 가지는 주체입니다. 따라서 액터의 상태 변경 및 복제 전파는 서버가 담당하며, 클라이언트는 서버로부터 복제된 데이터를 수신하여 적용합니다 ([Network] Network Property :: 치킨 날다) ([Network] Network Property :: 치킨 날다). 이를 Authority 모델이라고 하며, Unreal Engine은 이 모델을 따릅니다. 핵심 사항은 다음과 같습니다:
- 서버만 액터를 복제합니다. 서버는 자신이 가진 Authority Actor들의 상태를 변경 감지하여 연결된 클라이언트들에게 해당 Actor를 주기적으로 복제(Replicate)하여 전송합니다 ([UE4] Role, Remote Role). 반대로 클라이언트는 결코 액터를 서버로 복제 전송하지 않습니다 ([UE4] Role, Remote Role). 즉, 클라이언트에서 어떤 Actor의 프로퍼티를 변경해도 그것이 자동으로 서버의 Actor에 반영되지는 않습니다. 서버로의 변경 전달은 오로지 RPC 호출이나 서버에 의한 확인을 통해서만 이뤄집니다.
- Authority 여부 판정: 코드에서 AActor::Role 값을 검사하거나 HasAuthority() 함수를 호출함으로써 현재 액터가 Authority를 가지고 있는지 알 수 있습니다. HasAuthority()는 내부적으로 Role == ROLE_Authority인지 확인하여 true/false를 리턴하며, Actor가 서버에서 실행 중이거나 (서버 권한) 또는 복제되지 않고 로컬에서만 존재할 때 true가 됩니다 (Role_Authority explanation needed. - C++ - Epic Developer Community Forums). 따라서 서버 전용 로직을 실행할 때 흔히 if (HasAuthority()) { ... } 패턴을 사용합니다. (블루프린트에서는 “Switch Has Authority” 노드를 사용하여 Authority인 경우와 아닌 경우를 분기합니다.)
- 복제 여부 결정: Actor의 bReplicates 프로퍼티가 true이고 Role이 Authority일 경우, 엔진은 이 Actor를 복제 대상으로 간주합니다. 구체적으로 **Role == ROLE_Authority이고 RemoteRole이 ROLE_SimulatedProxy 또는 ROLE_AutonomousProxy**로 설정되어 있으면, 해당 엔진 인스턴스(서버)가 그 액터를 원격으로 복제하여 전송하는 역할을 수행하게 됩니다 ([UE4] Role, Remote Role). 반대로 RemoteRole이 None이면 복제되지 않습니다. 요컨대 서버에서 Authority인 액터만이 네트워크 상에 자신의 복제본을 가질 수 있고, RemoteRole 값이 그 복제본들의 형태를 정의합니다.
- 클라이언트 권한 및 제약: 클라이언트는 Authority가 아닌 Actor(즉, SimulatedProxy나 AutonomousProxy)에 대해서는 직접 상태를 변경하거나 서버에 영향을 줄 수 없습니다 ([UE5] Actor Role, Remote Role). AutonomousProxy의 경우 플레이어 입력을 통해 이동 등을 변경하지만, 이 또한 결국 서버에 RPC로 요청하여 서버의 Authority Actor에 적용되고 다시 복제되는 식으로 동작합니다. SimulatedProxy는 아예 RPC 호출 권한이 없고, 완전히 수동적으로 서버 업데이트를 따릅니다. 정리하면, 실질적인 게임 로직의 권한은 서버에 집중되며, 클라이언트는 소유한 액터에 한해 제한적으로 상호작용(예: 입력 처리 및 서버 요청)을 하는 것입니다.
- Owner과 Role의 관계: Actor의 Owner는 RPC 호출 권한 및 시각화 범위 등에서 사용되는 개념으로, 어떤 클라이언트를 Actor의 소유자로 지정하면 그 클라이언트는 해당 Actor에 대한 RPC를 서버로 보낼 수 있는 권한을 얻게 됩니다. 하지만 Owner를 설정하는 것만으로 Role 값이 자동으로 AutonomousProxy로 바뀌지는 않습니다 (What makes an actor Autonomous Proxy? - Multiplayer & Networking - Epic Developer Community Forums). AutonomousProxy로의 전환은 서버 측에서 명시적으로 SetAutonomousProxy(true)를 호출해야 이루어지며, 언리얼 엔진은 Pawn이 플레이어에 의해 Possess될 때 이 함수를 호출하여 Pawn 및 관련된 Actor들을 AutonomousProxy로 설정합니다 (What makes an actor Autonomous Proxy? - Multiplayer & Networking - Epic Developer Community Forums). 이를 통해 해당 플레이어의 클라이언트에서 그 Actor가 LocalRole=AutonomousProxy로 동작하게 됩니다.
Role 관련 코드 사용 예시
네트워크 Role 개념은 게임 코드에서 조건 분기나 함수 호출을 통해 활용됩니다. 아래에 간단한 C++ 예시와 함께 설명을 제공합니다:
void AMyActor::BeginPlay()
{
Super::BeginPlay();
// 예시 1: 서버에서만 실행할 로직
if (HasAuthority())
{
// 이 블럭은 서버에서만 실행됩니다 (Role == Authority).
InitializeGameState(); // 예: 게임 상태 초기화 (서버 권한으로만 수행)
}
// 예시 2: 로컬 클라이언트 전용 로직
if (GetLocalRole() == ROLE_AutonomousProxy)
{
// 이 블럭은 해당 Actor를 소유한 클라이언트에서만 실행됩니다.
ShowLocalPlayerUI(); // 예: 자기 캐릭터 전용 UI 표시
}
// 예시 3: 모든 클라이언트에서 실행할 로직
if (GetLocalRole() < ROLE_Authority)
{
// Role < Authority 즉, 클라이언트(AutonomousProxy 또는 SimulatedProxy)에서만 실행
PlayClientFX(); // 예: 모든 클라이언트에 이펙트 재생
}
}
위 코드에서 HasAuthority()를 사용한 부분은 서버에서만 실행되어야 하는 코드를 보호합니다. 이는 곧 Role == ROLE_Authority인지를 확인하는 것과 동일하며 (Role_Authority explanation needed. - C++ - Epic Developer Community Forums), 예를 들어 게임 시작 초기화나 주요 게임 로직은 서버에서만 수행되도록 보장할 때 사용합니다. 두 번째 분기에서는 GetLocalRole() 값이 ROLE_AutonomousProxy인지 확인하여, 자신이 소유한 액터에서만 수행되는 클라이언트 전용 로직을 넣고 있습니다. 예를 들어 각 플레이어 클라이언트에서 자기 캐릭터에 대해서만 UI를 표시하거나 입력을 받는 처리를 할 때 이런 체크를 활용합니다. 세 번째 if 분기는 GetLocalRole() < ROLE_Authority를 조건으로 사용했는데, 이는 현재 코드가 클라이언트 측에서 실행되고 있음을 뜻합니다 (ROLE_AutonomousProxy 또는 ROLE_SimulatedProxy일 경우 해당) (Role_Authority explanation needed. - C++ - Epic Developer Community Forums). 이런 조건을 통해 모든 클라이언트에서 실행되어야 하는 효과 등을 일괄 처리할 수 있습니다. 예를 들어 서버에서 어떤 이벤트 발생 시, 서버에서 멀티캐스트 RPC를 호출하지 않고 각 클라이언트의 Tick에서 Role < Authority 조건으로 효과를 재생하게 할 수도 있습니다 (Role_Authority explanation needed. - C++ - Epic Developer Community Forums).
또 다른 예로, **블루프린트(Blueprint)**에서는 Authority 핀과 Remote 핀을 가진 “Switch Has Authority” 노드를 제공하여, 현재 실행 컨텍스트가 서버인지 클라이언트인지를 쉽게 분기할 수 있습니다. 이를 통해 C++의 if (HasAuthority())와 유사하게 서버 전용 vs 클라이언트 전용 동작을 구현합니다. 또한 블루프린트에서 GetLocalRole/GetRemoteRole 노드를 사용하면 현재 액터의 역할을 열거형으로 얻을 수 있으며, 이를 화면에 출력하거나 로직 분기에 활용할 수 있습니다 (예: 디버그 목적으로 플레이어 캐릭터 머리 위에 “Authority/Autonomous/Simulated” 등을 표시) ([UE5] Actor Role, Remote Role) ([UE5] Actor Role, Remote Role).
정리 및 참고
언리얼 엔진의 Role 개념은 네트워크 플레이에서 매우 중요한 권한 관리 메커니즘입니다. Local Role은 액터가 현재 실행 중인 머신에서 어떤 권한 상태인지를 나타내고, Remote Role은 반대편에 그 액터가 어떤 상태로 존재하는지 알려줍니다 ([UE5] Network Role). 서버는 항상 Authority 역할을 가지며 액터 상태의 **진실된 소스(authoritative source)**가 되고, 클라이언트는 서버의 결정을 복제받아 반영하거나 자신이 소유한 액터에 한해 예측 수행 및 서버에 요청을 할 수 있습니다. Role과 RemoteRole 값을 올바르게 이해하고 사용하면, 어디서 어떤 코드를 실행해야 할지, 어떤 액터를 누구가 변경할 수 있을지, RPC를 어떻게 보낼지 등을 효과적으로 제어할 수 있습니다.
참고 자료: 언리얼 엔진 공식 문서 – Networking - Actors - Roles (액터 롤 및 리모트 롤) ([UE4] Role, Remote Role) ([UE4] Role, Remote Role), 언리얼 엔진 포럼 및 위키 설명 (Role_Authority explanation needed. - C++ - Epic Developer Community Forums) (UnrealWiki: Role), 그리고 언리얼 개발자들의 블로그 자료 ([Network] Network Property :: 치킨 날다) ([UE5] Actor Role, Remote Role) 등을 참고하여 작성했습니다. Role의 개념과 동작 방식에 대한 정확한 이해는 안정적인 멀티플레이 게임플레이 구현에 필수적입니다. 각 개발 상황에 맞게 Role을 활용하여 권한이 필요한 로직은 서버에서, 부가 연출은 클라이언트에서 수행하도록 설계하시기 바랍니다.
'UnraealEngine' 카테고리의 다른 글
| Data Asset vs Primary Data Asset (1) | 2025.03.26 |
|---|---|
| 저장 시스템 (0) | 2025.03.14 |
| 언리얼 엔진 5 리플리케이션(Replication) 심층 가이드 (0) | 2025.03.14 |
| 언리얼 엔진 5에서 스팀 OSS 기능 구현 가이드 (0) | 2025.03.13 |
| 언리얼 엔진 5 멀티플레이어 가이드: 세션 관리 & Net Role/Authority 심층 (0) | 2025.03.13 |