블루프린트에서의 리플리케이션
변수 복제와 RepNotify·RPC·액터 복제를 설정하고 서버 권한 기준으로 아이템 획득을 동기화합니다.
지난 두 절에서는 게임 모드, 스테이트, 컨트롤러, 폰 클래스가 게임 규칙/상태/조작을 어떻게 분담하는지 살펴봤습니다.
이 구조는 특히 멀티플레이어 게임에서 중요하며, 이를 가능하게 하는 핵심 메커니즘이 리플리케이션(Replication), 즉 네트워크 복제입니다.
이번 절에서는 블루프린트에서 리플리케이션이 어떻게 동작하고, 상태/이벤트를 네트워크로 동기화하는지 정리합니다.
리플리케이션이란 무엇인가?
리플리케이션(Replication)은 멀티플레이어 게임 환경에서 서버와 클라이언트 간에 게임의 상태(변수, 오브젝트의 위치 등)와 이벤트(함수 호출)를 네트워크를 통해 동기화하는 과정을 의미합니다.
언리얼 엔진은 서버-클라이언트 모델을 기반으로 하며, 서버가 게임의 진실된 상태를 소유하고 관리하며, 이 상태를 관련성(Relevancy), 복제 조건, 갱신 일정에 따라 필요한 클라이언트에 전달합니다.
리플리케이션이 필요한 이유- 게임 상태 동기화: 모든 플레이어의 컴퓨터가 동일한 게임 월드와 상태를 공유해야 합니다. (예: 다른 플레이어의 캐릭터 위치, 아이템 획득 여부, 적의 체력 등)
- 공정한 게임플레이: 서버가 모든 중요한 게임 로직(데미지 계산, 충돌 처리 등)을 처리함으로써 클라이언트 요청을 검증할 수 있습니다. 서버 사용만으로 치팅이 자동 방지되는 것은 아닙니다.
- 효율적인 네트워크 통신: 언리얼 엔진은 필요한 데이터만 효율적으로 복제하여 네트워크 대역폭 사용을 최적화합니다.
블루프린트에서 리플리케이션 설정하기
블루프린트에서 리플리케이션을 설정하는 방법은 크게 세 가지 유형으로 나눌 수 있습니다.
변수 리플리케이션
복제되는 액터의 변수를 서버에서 변경하면, 설정된 수신 범위로 상태를 전달할 수 있습니다. 중간의 모든 대입을 이벤트처럼 전달하거나 여러 변수를 동시에 갱신하는 보장은 없습니다.
변수 생성: 블루프린트에서 복제하고자 하는 변수(예: 플레이어의 Health, 적의 CurrentAmmo)를 생성합니다.
리플리케이션 설정: 변수를 선택하고 디테일(Details) 패널의 리플리케이션(Replication) 섹션에서 Replication 드롭다운을 Replicated로 설정합니다.
적용: 이제 서버에서 이 변수의 값을 변경하면, 클라이언트의 해당 액터 인스턴스에 있는 변수 값도 자동으로 업데이트됩니다.
- 주의:
RepNotify를 사용하여 변수 값이 복제된 후 특정 로직을 실행할 수 있습니다.
RepNotify (Rep_Notify):
RepNotify는 Replicated 변수가 클라이언트에 성공적으로 복제되어 값이 변경되었을 때 특정 함수를 자동으로 호출하는 기능입니다.
이를 통해 클라이언트에서 변수 값의 변화에 따른 시각적/청각적 효과를 구현할 수 있습니다.
- 설정: Blueprint 변수의
Replication드롭다운에서RepNotify를 선택합니다. 알림 함수(예:OnRep_Health)가 생성됩니다. - 활용: 알림 함수에서 체력 UI처럼 현재 값에 맞는 표시를 갱신합니다. Blueprint의 해당 변수
Set노드는 로컬에서도 알림을 호출하므로 서버에서의 대입도 이 경로에 들어갈 수 있습니다. 이를 네이티브 C++ 대입의 자동 동작으로 일반화하지 않습니다. 피격 한 번마다 반드시 효과를 재생해야 한다면 상태 복제와 별도의 이벤트 설계를 구분합니다.
함수 호출 리플리케이션 - RPC
특정 함수가 서버에서 실행되도록 클라이언트가 요청하거나, 서버에서 클라이언트에 특정 함수를 실행하도록 지시할 수 있습니다.
이를 RPC (Remote Procedure Call)라고 합니다.
Blueprint에서는 일반 함수가 아니라 커스텀 이벤트(Custom Event)의 Details에서 Replicates를 설정합니다. 아래에서 RPC 호출은 이 이벤트를 호출하는 뜻입니다.
Run on Server- 클라이언트의 공격 요청처럼 서버 판단이 필요한 동작을 보냅니다.
- 커스텀 이벤트의
Replicates를Run on Server로 설정합니다. - 클라이언트에서 전송하려면 호출 액터가 그 클라이언트 연결에 소유되어야 합니다. 월드의 문을 직접 소유하지 않았다면 자신의 PlayerController/Character RPC로 문 참조를 보내고 서버에서 거리·권한을 검증합니다. 서버 자신도 이 이벤트를 호출할 수 있습니다.
Multicast- 서버에서 호출하면 서버와 해당 액터가 현재 관련 있는 클라이언트에서 실행됩니다.
- 커스텀 이벤트를
Multicast로 설정합니다. 클라이언트에서 호출하면 그 클라이언트에서만 로컬 실행되며 다른 기기로 전파되지 않습니다. - 늦게 접속한 플레이어에게 과거 효과를 재생해 주는 저장소가 아니므로, 지속되어야 할 상태는 복제 변수로 표현합니다.
Run on Owning Client- 서버가 액터의 소유 클라이언트에 개별 피드백을 보낼 때 사용합니다.
- 커스텀 이벤트를
Run on Owning Client로 설정하고 올바른 소유 연결을 확인합니다. 서버가 소유하거나 소유 연결이 없는 액터에서는 서버 로컬 실행이 될 수 있으며, 클라이언트에서 부른 호출도 서버를 거쳐 전송되는 요청이 아닙니다.
액터 리플리케이션 (Replicating Actors)
서버에서 스폰한 액터(예: 아이템, 투사체, 적 AI)를 관련 클라이언트에 복제하도록 설정할 수 있습니다. 클라이언트의 로컬 스폰은 이 설정만으로 서버에 올라가지 않습니다.
액터 블루프린트 열기: 복제하고자 하는 액터 블루프린트 (예: BP_PickupItem)를 엽니다.
리플리케이션 설정: 클래스 디폴트(Class Defaults)를 클릭하고 디테일(Details) 패널에서 리플리케이션(Replication) 섹션을 찾습니다.
Replicates: 액터 복제를 허용합니다. 임의의 컴포넌트와 그 변수까지 모두 자동 복제하는 옵션은 아니므로 각각의 지원과 설정을 확인합니다.Replicate Movement: 루트 컴포넌트의 위치·회전·속도 등 이동 상태 복제를 사용합니다. 자식 컴포넌트 변환이나 임의의 스케일 변경 전체를 이 옵션 하나로 보장하지 않습니다.Net Update Frequency: 액터를 복제 대상으로 검토하는 빈도에 영향을 줍니다. 실제 전송 횟수는 변경 여부·관련성·대역폭 등의 영향도 받습니다.
리플리케이션 흐름 및 중요 규칙
언리얼 엔진의 멀티플레이어 환경은 기본적으로 서버-클라이언트 모델입니다.- 서버의 권한: 점수·인벤토리 등 최종 게임 상태는 서버에서 검증하고 결정합니다. 클라이언트의 이동 예측이나 로컬 시각 효과까지 모두 서버에서만 계산한다는 뜻은 아닙니다.
Has Authority는 해당 액터의 권한을 검사하므로 클라이언트에서만 만든 비복제 액터에도 참일 수 있습니다. - Reliable: 활성 연결에서 확인 응답까지 재전송하는 RPC입니다. 연결 단절 이후의 영구 전달이나 서로 다른 액터 간의 전역 실행 순서를 보장하지 않습니다. 잦은 호출을 무조건 Reliable로 만들면 지연과 큐 부담이 커집니다.
- Unreliable: 손실될 수 있는 RPC입니다. 이전 효과의 유실을 허용하는 순간 피드백 등에 사용하며, 임의의 호출을 자동으로 최신 호출로 합쳐 주는 기능은 아닙니다.
- 오너십: 플레이어가 빙의한 Pawn은 그 PlayerController의 소유 연결을 통해 RPC가 라우팅됩니다. AIController는 서버에서 제어합니다. 소유권은 호출 경로이며 요청 내용의 타당성 검사를 대신하지 않습니다.
리플리케이션 예시: 아이템 줍기
플레이어가 아이템을 주웠을 때, 이 아이템이 모든 클라이언트의 월드에서 사라지고, 플레이어의 인벤토리에 추가되는 로직을 리플리케이션으로 구현해봅시다.
서버의 획득 판단과 두 결과
BP_PickupItem의 서버 OverlapReplicates를 켜고 움직이는 아이템이면Replicate Movement도 설정합니다. 양쪽 충돌 컴포넌트의 Overlap 조건을 구성합니다.On Component Begin Overlap에서Other Actor를BP_PlayerCharacter로 캐스트하고, 서버가 스폰한 이 아이템의Has Authority를 검사합니다.- 서버 경로에서 캐릭터의 일반 함수
TryPickupItem에 아이템 참조를 전달합니다. 이미 서버에서 시작했으므로 여기서 Server RPC를 한 번 더 보낼 필요는 없습니다.
TryPickupItem- 아이템 참조가 유효하고 아직 획득되지 않았는지, 캐릭터와의 거리와 인벤토리 공간이 허용되는지 검사합니다.
- 통과하면 아이템의 획득 중 플래그를 먼저 설정하고, 잠복 노드 없이 인벤토리 갱신과 아이템 파괴를 처리합니다. 실패 경로에서는 상태를 바꾸지 않습니다.
- 아이템 위치를 파괴 전에 저장합니다. 인벤토리는 서버 데이터로 관리하고 필요한 소유 클라이언트에 복제하며, UI는 그 상태를 받아 갱신합니다.
- 서버에서 캐릭터의
Multicast_PlayPickupEffect를 저장한 위치와 함께 호출합니다.
Multicast_PlayPickupEffect- 커스텀 이벤트를
Multicast로 설정하고 전달받은 위치에서Play Sound at Location과 효과를 재생합니다. 이미 파괴한 아이템 참조에서 위치를 다시 읽지 않습니다. - 전용 서버는 시각·청각 효과를 건너뜁니다. 해당 캐릭터가 관련 있는 클라이언트가 수신 대상이며, 획득 상태 자체는 이 순간 효과에 의존하지 않습니다.
입력 버튼으로 줍기를 요청하는 변형에서는 소유 캐릭터에 Server_PickupItem 커스텀 이벤트를 두고, 서버의 같은 TryPickupItem 검사를 호출합니다. 클라이언트가 보낸 참조만 믿고 인벤토리를 갱신하지 않습니다.
이러한 방식으로 서버가 모든 게임 로직을 처리하고, 필요한 정보와 시각적/청각적 피드백을 클라이언트에 복제함으로써 멀티플레이어 환경에서 일관된 게임 경험을 제공할 수 있습니다.
블루프린트 네트워크 디버깅 팁
Net Mode변경: 에디터에서플레이(Play)버튼 옆의 드롭다운을 클릭하여Play As Client또는Listen Server모드로 테스트할 수 있습니다.Number of Players를 늘려 여러 클라이언트를 동시에 실행할 수도 있습니다.- 네트워크 통계: 게임 플레이 중
~키를 눌러 콘솔을 열고stat net을 입력하면 네트워크 대역폭 사용량, 패킷 손실률 등 다양한 네트워크 통계 정보를 확인할 수 있습니다. - 호출 위치 확인: RPC 진입점과 RepNotify에 액터 이름·권한·소유 여부를 함께 출력하여 어느 인스턴스에서 실행됐는지 구분합니다. 더 자세한 패킷 분석은 Networking Insights 캡처를 사용합니다.
리플리케이션은 멀티플레이어 게임 개발의 핵심이자 가장 복잡한 부분 중 하나입니다.
서버-클라이언트 모델과 각 클래스의 역할, 그리고 리플리케이션의 종류와 규칙을 명확히 이해하는 것이 중요합니다.
GAS(게임플레이 능력 시스템)를 사용하는 경우에도 동일한 원칙이 적용됩니다.
능력 실행 권한, 코스트/쿨다운 적용, 예측 보정 흐름은 9장 5절의 멀티플레이어 기준 실행 흐름과 함께 보면 구현 실수를 줄일 수 있습니다.
이번 절에서는 언리얼 엔진 블루프린트에서 리플리케이션이 어떻게 작동하며, 변수, 함수, 액터의 복제를 통해 게임의 상태와 이벤트를 네트워크를 통해 동기화하는 방법에 대해 알아보았습니다.
리플리케이션은 멀티플레이어 게임의 핵심이자 안정적인 게임플레이를 위한 필수 요소입니다.