Post

2026-06-24 TIL (83일차)

2026-06-24 TIL (83일차)

[UE] Remote Procedure Call (RPC) 완벽 가이드

멀티플레이어 게임에서 다른 컴퓨터(서버 혹은 클라이언트)에 있는 함수를 원격으로 실행하게 해주는 통신 기법인 RPC의 핵심 개념과 동작 원리를 정리합니다.

1. RPC의 기본 개념과 용도

  • 정의: 로컬 컴퓨터에서 함수를 호출하면, 네트워크로 연결된 다른 컴퓨터(타겟)에서 해당 함수가 실행되도록 하는 시스템. (간접 실행 방식인 Invoke에 해당)
  • 주요 용도: 코스메틱 효과(사운드, 파티클 재생), 일시적인 애니메이션 재생, 클라이언트의 입력 전달 등. (지속적으로 유지되어야 하는 상태 데이터는 ‘프로퍼티 레플리케이션’을 사용합니다.)

2. 가장 중요한 핵심: Ownership (소유권)

RPC가 정상적으로 작동하려면 액터의 소유권(Ownership)을 반드시 파악해야 합니다. 이는 단순히 통신 방향뿐만 아니라 ‘해킹 방지(보안)’와 직결됩니다.

  • 왜 중요한가? 만약 내가 남의 캐릭터(다른 클라이언트가 소유한 액터)에서 Server_GiveMeHealth() 같은 RPC를 호출할 수 있다면 게임은 해커들의 놀이터가 될 것입니다.
  • 언리얼 엔진은 “해당 액터를 소유한 클라이언트(Owning Client)만이 그 액터를 통해 서버로 RPC를 보낼 수 있다”는 강력한 보안 규칙을 가지고 있습니다.

3. 누락된 3개의 핵심 표 (RPC 라우팅 테이블)

RPC 매크로(Server, Client, NetMulticast)와 ‘호출하는 곳’, ‘액터의 소유권’에 따라 함수가 어디서 실행되는지 나타내는 언리얼 공식 표입니다. 무작정 외우기보다 “서버가 허락한 길만 열린다”는 원리로 이해하면 쉽습니다.

① Server RPC (클라이언트 ➡️ 서버로 요청)

오직 자신이 소유한 액터에서만 서버로 요청을 보낼 수 있습니다. 남의 액터에서 호출하면 무시됩니다.

호출하는 곳 (Calling PC)액터 소유권 (Ownership)실행되는 곳 (Executing PC)
ClientOwning Client (내가 소유)Server (정상 실행)
ClientNon-Owning Client (남이 소유)Dropped (무시됨 - 보안 차단)
ClientUnowned (소유자 없음)Dropped (무시됨)
Server(소유권 상관없음)Server (로컬에서 즉시 실행됨)

② Client RPC (서버 ➡️ 특정 클라이언트로 명령)

서버가 특정 클라이언트 한 명에게만 콕 집어서 지시를 내릴 때 사용합니다.

호출하는 곳 (Calling PC)액터 소유권 (Ownership)실행되는 곳 (Executing PC)
ServerOwning Client (특정 유저 소유)해당 Owning Client
ServerUnowned (소유자 없음)Server (로컬에서 실행됨)
Client(소유권 상관없음)호출한 Client (로컬에서 실행됨)

③ NetMulticast RPC (서버 ➡️ 모두에게 방송)

서버가 방장으로서 접속한 모든 컴퓨터(서버 포함)에게 지시를 내립니다. 폭발 이펙트나 전체 시스템 메시지에 쓰입니다.

호출하는 곳 (Calling PC)액터 소유권 (Ownership)실행되는 곳 (Executing PC)
Server(소유권 상관없음)Server 및 연결된 모든 Client
Client(소유권 상관없음)호출한 Client (로컬에서만 실행됨 - 방송 안됨)

4. C++ 실제 구현 문법 (Syntax)

RPC를 C++로 구현할 때는 헤더 파일의 선언부와 소스 파일의 구현부 이름이 달라진다는 점이 매우 중요합니다.

헤더 파일 (.h) 선언

1
2
3
4
5
6
7
8
9
10
11
// 1. Server RPC (+ 검증 로직 포함)
UFUNCTION(Server, Reliable, WithValidation)
void Server_EquipWeapon();

// 2. Client RPC
UFUNCTION(Client, Unreliable)
void Client_ShowHitMarker();

// 3. NetMulticast RPC
UFUNCTION(NetMulticast, Unreliable)
void Multicast_PlayExplosionEffect();

소스 파일 (.cpp) 구현

함수 이름 뒤에 엔진이 자동으로 생성하는 접미사인 _Implementation을 반드시 붙여서 구현해야 합니다. (WithValidation이 있다면 _Validate도 구현해야 합니다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 실제 서버에서 실행될 로직
void AMyCharacter::Server_EquipWeapon_Implementation()
{
    // 무기 장착 로직
}

// 서버에서 이 RPC를 실행해도 되는지 검사하는 보안 로직 (WithValidation)
bool AMyCharacter::Server_EquipWeapon_Validate()
{
    // 예: 살아있는 상태일 때만 무기 장착을 허락함
    if (Health > 0) return true;
    return false; // false 반환 시 요청한 클라이언트를 강제 퇴장(Kick)시킴
}

void AMyCharacter::Client_ShowHitMarker_Implementation()
{
    // 클라이언트 화면에만 피격 마커 UI 띄우기
}

주의사항: Reliable과 NetMulticast의 조합

  • Unreliable (기본값): 패킷이 유실되어도 재전송하지 않습니다. (사운드, 이펙트 등 덜 중요한 데이터)
  • Reliable: 패킷이 유실되면 도착할 때까지 네트워크 채널을 꽉 잡고 계속 재전송합니다. (데미지, 스폰, 퀘스트 완료 등 핵심 데이터)
  • 경고: NetMulticastReliable을 함께 사용하는 것은 최대한 피해야 합니다. 다수의 유저에게 무조건 도달할 때까지 패킷을 쏘게 되므로, 네트워크 트래픽이 폭주하여 대규모 렉(Lag)을 유발할 수 있습니다.
This post is licensed under CC BY 4.0 by the author.