요약

개념 기준 역할
NetMode World / Process 현재 실행 환경이 서버인지 클라이언트인지 구분
NetDriver World의 네트워크 드라이버 Connection, RPC, Replication 관리
NetConnection 머신 간 연결 서버-클라이언트 통신 경로
Ownership Actor 소유 관계 Actor가 어떤 클라이언트 Connection에 속하는지 결정
Authority Actor 권한 이 Actor의 상태를 누가 최종 결정하는지 판단
항목 요약
NetMode 현재 World가 Standalone, Client, ListenServer, DedicatedServer 중 어떤 모드인지 나타냄
NM_Standalone 싱글플레이. 서버/클라이언트 로직이 한 프로세스에서 실행
NM_Client 서버에 접속한 클라이언트. 서버 권한 로직은 실행하지 않음
NM_ListenServer 서버이면서 로컬 플레이어도 있는 호스트
NM_DedicatedServer 로컬 플레이어 없는 전용 서버
NetDriver 네트워크 통신, Replication, RPC, Connection을 관리
NetConnection 서버와 클라이언트 사이의 연결 객체
ServerConnection 클라이언트가 서버와 통신하기 위해 가진 연결
ClientConnections 서버가 접속한 클라이언트마다 가진 연결 배열
Ownership RPC와 Owner-only Replication의 기준이 되는 소유 관계
GameMode 서버에만 존재. 클라이언트 GetGameMode()nullptr 가능
PlayerController 서버와 소유 클라이언트에 존재. 다른 클라이언트에는 없음
Pawn / GameState / PlayerState 서버와 클라이언트에 복제되어 존재

서버가 결과를 확정하고, 클라이언트는 요청과 표시를 담당한다. NetMode는 현재 코드가 어느 네트워크 실행 환경에서 돌고 있는지 확인하는 기준이고, NetConnection과 Ownership은 RPC와 Replication의 대상 클라이언트를 결정하는 기준이다.


Unreal의 네트워크 구조는 서버가 authoritative하게 게임 상태를 관리하고, 클라이언트는 서버로부터 복제된 상태를 받는 구조를 기본으로 한다.

flowchart LR
    A[Client 입력] --> B[Server RPC]
    B --> C[서버에서 검증 / 처리]
    C --> D[HP 감소 / 상태 변경]
    D --> E[Replication]
    E --> F[Client 화면 갱신]

NetMode

NetMode현재 게임 프로세스 또는 World가 네트워크에서 어떤 역할로 실행 중인지 나타낸다.

ENetMode 의미
NM_Standalone 싱글플레이 또는 로컬 플레이. 서버/클라이언트 로직을 같은 프로세스에서 처리
NM_Client 서버에 접속한 클라이언트
NM_ListenServer 서버이면서 로컬 플레이어도 직접 참여하는 호스트
NM_DedicatedServer 로컬 플레이어 없이 서버 기능만 수행하는 전용 서버

ENetMode에는 NM_Standalone, NM_DedicatedServer, NM_ListenServer, NM_Client가 정의되어 있다. NM_ListenServer는 로컬 플레이어가 함께 존재하는 서버이고, NM_DedicatedServer는 로컬 플레이어 없이 원격 클라이언트 연결을 처리하는 서버다.

NetMode 서버 로직 클라이언트 로직 로컬 플레이어
NM_Standalone 실행 실행 있음
NM_Client 실행 안 함 실행 있음
NM_ListenServer 실행 실행 있음
NM_DedicatedServer 실행 실행 안 함 없음

NM_Standalone은 원격 클라이언트 연결이 없는 모드지만, 서버 측 로직과 클라이언트 측 로직이 함께 동작한다. 이 때문에 멀티플레이를 기준으로 작성한 로직이 싱글플레이 Standalone에서도 동작할 수 있다.


ENetMode확인하는 코드

ENetMode NetMode = GetWorld()->GetNetMode();
ENetMode NetMode = GetNetMode();

Component에서 확인

if (GetNetMode() == NM_Client)
{
    // 클라이언트 전용 처리
}
if (GetNetMode() != NM_Client)
{
    // 서버 또는 Standalone에서 처리
}

HasAuthority

특정 Actor에 대해 현재 머신이 권한을 가지고 있는지 확인

구분 기준
GetNetMode() 현재 World가 Client인지, ListenServer인지, DedicatedServer인지
HasAuthority() 이 Actor의 Authority가 현재 머신에 있는지
GetLocalRole() 현재 머신에서 이 Actor가 가진 Role
GetRemoteRole() 원격 머신에서 이 Actor가 가질 Role

서버 권한으로 실행되어야 하는 Actor 로직은 HasAuthority()로 방어한다.

void AMyCharacter::ApplyDamage_ServerOnly(float Damage)
{
    if (!HasAuthority())
    {
        return;
    }

    Health -= Damage;
}

NetMode는 디버깅과 실행 환경 구분에 유용하고, HasAuthority()는 Actor 단위의 서버 권한 판단에 더 직접적이다.


멀티플레이에서는 같은 C++ 코드가 여러 프로세스에서 실행된다.

flowchart LR
    A[Server Process] --> D[같은 BeginPlay 코드 실행]
    B[Client 1 Process] --> D
    C[Client 2 Process] --> D

APlayerCharacter::BeginPlay() 하나만 보더라도 서버, 내 클라이언트, 다른 클라이언트에서 각각 실행될 수 있다.

상황 확인할 것
코드가 몇 번 실행되는가 서버/클라이언트 각각 실행 여부
어느 컴퓨터에서 실행되는가 GetNetMode() 로그
이 Actor를 누가 제어하는가 Ownership / Role
서버 권한이 있는가 HasAuthority()
특정 클라이언트 소유 Actor인가 Owning Connection

NetDriver

UObjectFExec를 상속하는 네트워크 드라이버 클래스
네트워크 통신의 핵심 관리 객체

항목 설명
역할 네트워크 연결, 패킷 처리, Replication, RPC 전송 관리
생성 시점 멀티플레이 네트워크가 열릴 때
싱글플레이 일반적으로 NetDriver 없음
서버 접속한 클라이언트들의 Connection 관리
클라이언트 서버로 향하는 Connection 관리

서버가 ClientConnections 배열을 통해 클라이언트 연결들을 관리한다.

// 개념 구조
UWorld
└── UNetDriver
    ├── ServerConnection      // 클라이언트일 때 서버와의 연결
    └── ClientConnections[]   // 서버일 때 클라이언트들과의 연결

NetDriver NetMode

UWorld는 NetDriver가 있으면 NetDriver를 통해 NetMode를 판단한다.

ENetMode UWorld::InternalGetNetMode() const
{
    if (NetDriver != nullptr)
    {
        const bool bIsClientOnly = IsRunningClientOnly();
        return bIsClientOnly ? NM_Client : NetDriver->GetNetMode();
    }

    // NetDriver가 없으면 Standalone 계열
}

NetDriver 입장에서 서버인지 클라이언트인지는 ServerConnection 유무로 구분할 수 있다.

bool UNetDriver::IsServer() const
{
    return ServerConnection == nullptr;
}
상태 의미
ServerConnection == nullptr 이 NetDriver는 서버 역할
ServerConnection != nullptr 이 NetDriver는 클라이언트 역할
서버 + 로컬 플레이어 있음 Listen Server
서버 + 로컬 플레이어 없음 Dedicated Server

NetConnection

다른 머신과의 네트워크 연결을 나타내는 객체
UPlayer를 상속하며, 자신을 소유한 NetDriver를 가진다.

위치 Connection 구조
서버 접속한 클라이언트 수만큼 ClientConnections 보유
클라이언트 서버를 향한 ServerConnection 하나 보유

Driver는 owning net driver로 설명된다.

flowchart TD
    A[Server NetDriver] --> B[ClientConnection 1]
    A --> C[ClientConnection 2]
    A --> D[ClientConnection 3]

    E[Client 1 NetDriver] --> F[ServerConnection]
    G[Client 2 NetDriver] --> H[ServerConnection]

서버, 클라이언트 Connection 구조

머신 NetDriver NetConnection
Dedicated Server 있음 ClientConnections[]
Listen Server 있음 ClientConnections[] + 로컬 플레이어
Client 있음 ServerConnection
Standalone 보통 없음 없음

서버는 여러 클라이언트와 연결되어 있으므로 ClientConnections를 여러 개 가진다.
클라이언트는 하나의 서버에 접속하므로 ServerConnection 하나를 가진다.


Ownership

Ownership은 어떤 클라이언트 Connection이 특정 Actor를 소유하는지를 결정하는 관계다.

개념 설명
Owner Actor의 소유자 Actor
Owning Connection 해당 Actor를 소유한 클라이언트 연결
PlayerController 보통 클라이언트 Connection의 핵심 소유 Actor
Pawn PlayerController가 Possess하면 Owner 경로를 통해 Connection을 찾을 수 있음
Weapon / Item Actor Owner를 Pawn 또는 Controller로 설정하면 소유 관계에 포함 가능

Actor의 owner와 owning connection은 RPC 실행 위치와 replication 대상 판단에 중요하다. Client RPC는 어느 클라이언트에서 실행할지 알아야 하며, 이때 Actor의 owning connection이 사용된다.

flowchart LR
    A[ClientConnection] --> B[PlayerController]
    B --> C[Pawn]
    C --> D[Weapon Actor]

GetNetConnection

Actor는 자신의 Owner를 통해 NetConnection을 확인

UNetConnection* AActor::GetNetConnection() const
{
    return Owner ? Owner->GetNetConnection() : nullptr;
}

Pawn은 Controller가 있으면 Controller의 NetConnection을 사용

UNetConnection* APawn::GetNetConnection() const
{
    if (Controller)
    {
        return Controller->GetNetConnection();
    }

    return Super::GetNetConnection();
}

PlayerController는 Player가 있으면 자신의 NetConnection을 반환

UNetConnection* APlayerController::GetNetConnection() const
{
    return (Player != nullptr) ? NetConnection : nullptr;
}
flowchart LR
    A[Weapon Actor GetNetConnection] --> B[Owner: Pawn]
    B --> C[Pawn Controller 확인]
    C --> D[PlayerController]
    D --> E[NetConnection 반환]

RPC와 Ownership

RPC 종류 실행 위치
Server RPC 클라이언트가 서버에 요청
Client RPC 서버가 특정 owning client에서 실행
NetMulticast RPC 서버에서 호출해 서버와 클라이언트들에 전파

RPC는 valid ownerowning connection이 있는 replicated actor 또는 actor component에서 실행되어야 한다.

상황 결과
Client가 자신이 소유한 Actor에서 Server RPC 호출 서버에서 실행 가능
Client가 소유하지 않은 Actor에서 Server RPC 호출 실행되지 않거나 무시될 수 있음
Server가 Client RPC 호출 Actor의 owning connection 클라이언트에서 실행
Owning Connection 없음 Client RPC 대상 불명확

Actor 존재 범위

객체 서버 소유 클라이언트 다른 클라이언트
GameMode
GameState
PlayerController
PlayerState
Pawn / Character
Replicated Actor
UI Widget

GameMode는 서버에만 존재함

AGameModeBase* GM = UGameplayStatics::GetGameMode(this);

if (!IsValid(GM))
{
    return;
}

클라이언트에서 GameMode 로직이 필요하면 서버 RPC로 요청하거나, 서버에서 실행되는 함수 내부에서 처리

if (HasAuthority())
{
    AGameModeBase* GM = UGameplayStatics::GetGameMode(this);
}

GameMode, GameState

구분 GameMode GameState
존재 위치 서버에만 존재 서버와 클라이언트에 존재
용도 게임 규칙, 승패 판정, 스폰 규칙 클라이언트도 알아야 하는 게임 상태
클라이언트 접근 불가 또는 nullptr 가능
복제(Replication) 직접 클라에 존재하지 않음 복제됨

클라이언트도 알아야 하는 점수, 남은 시간, 매치 상태는 GameState

반응형

'Unreal Engine' 카테고리의 다른 글

UE Angel Script Override  (0) 2026.08.06
게임 프로젝트에도 UE Public/Private 구조가 필요할까?  (0) 2026.08.04
MyaCat 정리 2  (0) 2026.07.28
MyaCat 정리 1  (0) 2026.07.27
AssetManager ⇄ Bundle System 구조 수정  (0) 2026.07.13