본문으로 건너뛰기

안동민 개발노트

본문 시작

블루프린트에서의 리플리케이션

변수 복제와 RepNotify·RPC·액터 복제를 설정하고 서버 권한 기준으로 아이템 획득을 동기화합니다.

지난 두 절에서는 게임 모드, 스테이트, 컨트롤러, 폰 클래스가 게임 규칙/상태/조작을 어떻게 분담하는지 살펴봤습니다.

이 구조는 특히 멀티플레이어 게임에서 중요하며, 이를 가능하게 하는 핵심 메커니즘이 리플리케이션(Replication), 즉 네트워크 복제입니다.

이번 절에서는 블루프린트에서 리플리케이션이 어떻게 동작하고, 상태/이벤트를 네트워크로 동기화하는지 정리합니다.

블루프린트에서의 리플리케이션

클라이언트는 행동을 요청하고, 서버는 검증한 결과만 모든 플레이어에게 배포합니다.

  1. 블루프린트에서의 리플리케이션 흐름

    플레이어가 아이템 줍기를 시도하되 결과를 직접 확정하지 않습니다. ↓ 2 소유 클라이언트가 서버에 대상과 행동 의도를 전달합니다. ↓ 3 서버가 소유권·거리·중복 획득을 확인한 뒤 인벤토리를 변경합니다. ↓ 4 복제 변수와 RepNotify가 월드 제거·인벤토리 UI를 같은 상태로 맞춥니다.

  2. 클라이언트 입력

    플레이어가 아이템 줍기를 시도하되 결과를 직접 확정하지 않습니다.

  3. Server RPC 요청

    소유 클라이언트가 서버에 대상과 행동 의도를 전달합니다.

  4. 서버 검증·상태 변경

    서버가 소유권·거리·중복 획득을 확인한 뒤 인벤토리를 변경합니다.

  5. 클라이언트 결과 반영

    복제 변수와 RepNotify가 월드 제거·인벤토리 UI를 같은 상태로 맞춥니다.

  6. 데이터와 이벤트의 경계

    위치·체력·인벤토리는 복제 변수로 두어 늦게 접속한 클라이언트도 현재값을 받습니다. 피격 이펙트·사운드는 Multicast 또는 Client RPC로 한 번만 전달합니다. 클라이언트가 먼저 보여 준 예측 결과는 서버 응답과 다를 수 있으므로 롤백 또는 보정 처리 기준을 함께 둡니다.


리플리케이션이란 무엇인가?

리플리케이션(Replication)멀티플레이어 게임 환경에서 서버와 클라이언트 간에 게임의 상태(변수, 오브젝트의 위치 등)와 이벤트(함수 호출)를 네트워크를 통해 동기화하는 과정을 의미합니다.

언리얼 엔진은 서버-클라이언트 모델을 기반으로 하며, 서버가 게임의 진실된 상태를 소유하고 관리하며, 이 상태를 모든 클라이언트에 복제하여 동기화합니다.

리플리케이션이 필요한 이유
  • 게임 상태 동기화: 모든 플레이어의 컴퓨터가 동일한 게임 월드와 상태를 공유해야 합니다. (예: 다른 플레이어의 캐릭터 위치, 아이템 획득 여부, 적의 체력 등)
  • 공정한 게임플레이: 서버가 모든 중요한 게임 로직(데미지 계산, 충돌 처리 등)을 처리함으로써 클라이언트 조작(Cheating)을 방지하고 공정한 게임플레이를 보장합니다.
  • 효율적인 네트워크 통신: 언리얼 엔진은 필요한 데이터만 효율적으로 복제하여 네트워크 대역폭 사용을 최적화합니다.

블루프린트에서 리플리케이션 설정하기

블루프린트에서 리플리케이션을 설정하는 방법은 크게 세 가지 유형으로 나눌 수 있습니다.

변수 리플리케이션

액터의 특정 변수 값을 서버에서 변경하면, 해당 값이 자동으로 모든 클라이언트에 동기화되도록 설정할 수 있습니다.

변수 생성: 블루프린트에서 복제하고자 하는 변수(예: 플레이어의 Health, 적의 CurrentAmmo)를 생성합니다.

리플리케이션 설정: 변수를 선택하고 디테일(Details) 패널의 리플리케이션(Replication) 섹션에서 Replication 드롭다운을 Replicated로 설정합니다.

적용: 이제 서버에서 이 변수의 값을 변경하면, 클라이언트의 해당 액터 인스턴스에 있는 변수 값도 자동으로 업데이트됩니다.

  • 주의: RepNotify를 사용하여 변수 값이 복제된 후 특정 로직을 실행할 수 있습니다.

RepNotify (Rep_Notify): RepNotifyReplicated 변수가 클라이언트에 성공적으로 복제되어 값이 변경되었을 때 특정 함수를 자동으로 호출하는 기능입니다.

이를 통해 클라이언트에서 변수 값의 변화에 따른 시각적/청각적 효과를 구현할 수 있습니다.

  • 설정: 변수를 Replicated로 설정한 후, 드롭다운에서 Replicated Using을 선택합니다. 그러면 새로운 함수가 자동으로 생성됩니다. (예: OnRep_Health)
  • 활용: OnRep_Health 함수 내에 체력 바 UI 업데이트, 피격 사운드 재생, 데미지 이펙트 표시 등의 로직을 구현합니다. 이 함수는 서버에서도 호출되지만, 주로 클라이언트의 시각적 피드백을 위해 사용됩니다.

함수 호출 리플리케이션 - RPC

특정 함수가 서버에서 실행되도록 클라이언트가 요청하거나, 서버에서 클라이언트에 특정 함수를 실행하도록 지시할 수 있습니다.

이를 RPC (Remote Procedure Call)라고 합니다.

함수 세부 정보 패널에서 Replication 섹션의 Replicates 드롭다운을 통해 설정합니다.

Run on Server (서버에서 실행)
  • 클라이언트가 서버에 함수 실행을 요청할 때 사용합니다. (예: 플레이어가 공격 버튼을 눌렀을 때, 클라이언트가 서버에게 나 공격할게!라고 알림)
  • 설정: 함수를 생성하고 ReplicatesRun on Server로 설정합니다. Reliable 옵션을 체크하면 네트워크 불안정 시에도 반드시 호출되도록 보장합니다.
  • 주의: Run on Server 함수는 오직 소유권(Ownership)을 가진 클라이언트만이 호출할 수 있습니다. 일반적으로 PlayerControllerPawn/Character가 소유권을 가집니다. 다른 액터(예: 월드에 있는 문)의 함수를 서버에서 실행하고 싶다면, 그 액터에 대한 Run on Server 함수를 PlayerControllerPawn에 만들고, 거기서 다시 해당 액터의 함수를 호출하는 방식으로 우회해야 합니다.
Multicast (멀티캐스트)
  • 서버가 모든 클라이언트에 함수 실행을 지시할 때 사용합니다. (예: 서버가 모든 클라이언트는 이펙트 재생!이라고 알림)
  • 설정: 함수를 생성하고 ReplicatesMulticast로 설정합니다. Reliable 옵션을 체크하면 네트워크 불안정 시에도 반드시 호출되도록 보장합니다.
  • 주의: Multicast 함수는 오직 서버에서만 호출될 수 있습니다. 클라이언트에서 Multicast 함수를 호출하려 하면 경고가 뜨며 작동하지 않습니다. 이 함수는 서버에서도 실행되고, 모든 클라이언트에서도 실행됩니다.
Run on Owning Client (소유 클라이언트에서 실행)
  • 서버가 특정 폰/캐릭터의 소유권을 가진 클라이언트에만 함수 실행을 지시할 때 사용합니다. (예: 서버가 특정 플레이어에게만 너 데미지 입었어!라고 알림)
  • 설정: 함수를 생성하고 ReplicatesRun on Owning Client로 설정합니다. Reliable 옵션을 체크하면 네트워크 불안정 시에도 반드시 호출되도록 보장합니다.
  • 주의: 이 함수는 오직 서버에서만 호출될 수 있으며, 소유권을 가진 클라이언트에서만 실행됩니다.

액터 리플리케이션 (Replicating Actors)

게임 월드에 스폰되는 액터(예: 아이템, 투사체, 적 AI) 자체가 모든 클라이언트에 존재하도록 설정할 수 있습니다.

액터 블루프린트 열기: 복제하고자 하는 액터 블루프린트 (예: BP_PickupItem)를 엽니다.

리플리케이션 설정: 클래스 디폴트(Class Defaults)를 클릭하고 디테일(Details) 패널에서 리플리케이션(Replication) 섹션을 찾습니다.

  • Replicates: 체크합니다. (이 액터와 그 컴포넌트들이 모든 클라이언트에 복제되도록 허용)
  • Replicate Movement: 체크합니다. (액터의 위치, 회전, 스케일이 자동으로 복제되도록 함. 폰/캐릭터는 기본적으로 체크되어 있음)
  • Net Update Frequency: 해당 액터가 초당 몇 번 복제 업데이트를 보낼지 설정합니다. (높을수록 정확하지만 네트워크 부하 증가)

리플리케이션 흐름 및 중요 규칙

서버 권한 기반 Replication 실행

클라이언트 입력, 서버 RPC, 권한 검증, 변수 복제, 클라이언트 화면 반영까지 네트워크 흐름을 정리한다.

  1. 1
    클라이언트 요청

    플레이어 입력은 소유 Actor의 Server RPC로 서버에 전달된다. request

  2. 2
    서버 검증

    서버는 거리, 쿨다운, 권한, 상태를 확인하고 실제 값을 변경한다. authority

  3. 3
    변수 복제

    Replicated 변수와 RepNotify가 다른 클라이언트에 상태 변화를 전달한다. replicate

  4. 4
    시각 반영

    클라이언트는 애니메이션, UI, 효과를 복제된 상태에 맞춰 갱신한다. presentation

  5. 5
    권한 체크

    중요 상태는 클라이언트가 직접 바꾸지 않는다.

  6. 6
    소유권

    RPC가 무시될 때 Actor 소유 관계를 확인한다.

  7. 7
    대역폭

    자주 바뀌는 값은 복제 빈도와 조건을 조절한다.

언리얼 엔진의 멀티플레이어 환경은 기본적으로 서버-클라이언트 모델입니다.
  • 서버의 권한: 게임의 모든 핵심 로직, 상태 변경, 물리 시뮬레이션 등은 서버에서만 발생하고 결정됩니다. 클라이언트는 서버의 복제품을 가지고 있을 뿐입니다.
  • 신뢰성 (Reliable) vs. 비신뢰성 (Unreliable)
    • Reliable (신뢰성): 중요한 데이터나 이벤트에 사용합니다. 네트워크 상태가 나쁘더라도 반드시 전달되도록 보장합니다. (재전송 메커니즘 포함)
    • Unreliable (비신뢰성): 자주 업데이트되거나 실시간성이 중요한 데이터에 사용합니다. 데이터 손실이 허용되며, 최신 값으로 덮어쓰여지므로 지연이 발생해도 이전 값은 중요하지 않을 때 사용합니다. (예: 캐릭터 위치 업데이트, 프레임마다 변하는 값)
  • 오너십 (Ownership)
    • 폰(Pawn)은 하나의 컨트롤러(Controller) (플레이어 컨트롤러 또는 AI 컨트롤러)에 의해 소유됩니다.
    • 플레이어가 조작하는 폰은 해당 플레이어의 플레이어 컨트롤러가 소유합니다.
    • Run on Server RPC는 소유권을 가진 클라이언트만 호출할 수 있습니다.
    • AI가 제어하는 폰은 서버의 AI 컨트롤러가 소유합니다.
    • 소유권은 네트워크 통신 및 권한 부여에 중요한 역할을 합니다.

리플리케이션 예시: 아이템 줍기

아이템 줍기는 클라이언트 요청을 서버가 검증한 뒤 복제한다

보이는 즉시 사라지게 만들면 중복 획득과 치트에 약하므로 서버 권한 경로를 고정한다.

단계클라이언트서버결과
Input줍기 키 입력아직 상태 변경 없음요청 준비
Server RPC소유 Actor를 통해 요청 전송Run on Server 이벤트 수신권한 위치 전환
Validate대기거리, 소유권, 이미 획득 여부 검사중복 방지
Apply대기인벤토리 추가와 월드 아이템 제거진짜 상태 변경
ReplicateOnRep/UI 갱신변경된 상태 복제모든 화면이 같은 결과

플레이어가 아이템을 주웠을 때, 이 아이템이 모든 클라이언트의 월드에서 사라지고, 플레이어의 인벤토리에 추가되는 로직을 리플리케이션으로 구현해봅시다.

BP_PickupItem (아이템 액터)
  • 클래스 디폴트에서 ReplicatesReplicate Movement를 체크합니다.
  • 콜리전 컴포넌트의 On Component Begin Overlap 이벤트에서 로직을 시작합니다.
  • 이벤트 그래프
    • On Component Begin Overlap > Other ActorCast To BP_PlayerCharacter로 캐스팅합니다.
    • 캐스팅 성공 시, Has Authority 노드를 사용하여 현재 코드가 서버에서 실행 중인지 확인합니다. (아이템 줍기 로직은 서버에서만 처리해야 함)
    • Has AuthorityTrue일 경우:
      • Run on Server RPC (예: Server_PickupItem)를 호출합니다. 이 RPC에 BP_PlayerCharacter와 주운 아이템(Self 참조)을 파라미터로 넘깁니다.
BP_PlayerCharacter (플레이어 캐릭터)
  • 함수 생성: Server_PickupItem이라는 커스텀 이벤트를 만들고, ReplicatesRun on Server로 설정합니다.
  • Server_PickupItem 함수 내부
    • 아이템을 실제로 플레이어 인벤토리에 추가하는 로직을 구현합니다. (인벤토리 변수 업데이트 등)
    • 아이템 액터를 Destroy Actor 노드로 파괴합니다.
    • Multicast RPC (예: Multicast_PlayPickupEffect)를 호출하여 모든 클라이언트에 줍기 효과(사운드, 이펙트)를 재생하도록 지시합니다. (서버에서만 호출 가능)
BP_PlayerCharacter (계속)
  • 함수 생성: Multicast_PlayPickupEffect라는 커스텀 이벤트를 만들고, ReplicatesMulticast로 설정합니다.
  • Multicast_PlayPickupEffect 함수 내부
    • 아이템 줍는 사운드 (Play Sound at Location)
    • 아이템 줍는 이펙트 (Spawn Emitter at Location)
    • 주의: 이 함수는 서버와 모든 클라이언트에서 실행되므로, 이펙트/사운드 재생은 Is Dedicated Server 체크를 통해 전용 서버에서는 건너뛰거나, 필요하다면 Is Locally Controlled 체크를 통해 특정 클라이언트에서만 실행되도록 할 수 있습니다.

이러한 방식으로 서버가 모든 게임 로직을 처리하고, 필요한 정보와 시각적/청각적 피드백을 클라이언트에 복제함으로써 멀티플레이어 환경에서 일관된 게임 경험을 제공할 수 있습니다.


블루프린트 네트워크 디버깅 팁

네트워크 버그는 실행 모드와 로그를 같이 좁힌다

리플리케이션이 보이지 않을 때는 노드부터 고치기보다 Play As Client , stat net , log net , showdebug net 순서로 권한과 전파 위치를 분리한다.

  1. 1
    실행 모드 고정

    Listen Server 와 Play As Client 를 구분하고 Number of Players 를 늘려 같은 상황을 재현한다.

  2. 2
    대역폭 확인

    stat net 으로 패킷 손실률과 네트워크 사용량을 본다. 너무 잦은 복제는 여기서 먼저 드러난다.

  3. 3
    RPC 흐름 추적

    log net 으로 Run on Server , Multicast , Run on Owning Client 가 실제로 호출되는지 확인한다.

  4. 4
    소유권 표시

    showdebug net 으로 Pawn, Controller, Owner 관계를 확인해 RPC가 도착할 대상을 찾는다.

  5. 5
    서버 RPC가 안 들어올 때

    Run on Server 호출한 클라이언트가 해당 Pawn이나 PlayerController를 소유하고 있는지 먼저 본다.

  6. 6
    이펙트가 한쪽만 보일 때

    Multicast 서버에서 호출했는지 확인한다. 클라이언트가 직접 호출한 멀티캐스트는 기대한 전파가 일어나지 않는다.

  7. 7
    전달은 되지만 지연될 때

    Reliable 중요하지 않은 반복 이벤트까지 Reliable로 보내고 있지 않은지 stat net 결과와 함께 줄인다.

  • Net Mode 변경: 에디터에서 플레이(Play) 버튼 옆의 드롭다운을 클릭하여 Play As Client 또는 Listen Server 모드로 테스트할 수 있습니다. Number of Players를 늘려 여러 클라이언트를 동시에 실행할 수도 있습니다.
  • 네트워크 통계: 게임 플레이 중 ~ 키를 눌러 콘솔을 열고 stat net을 입력하면 네트워크 대역폭 사용량, 패킷 손실률 등 다양한 네트워크 통계 정보를 확인할 수 있습니다.
  • RPC 호출 확인: log net 명령어를 통해 네트워크 로그를 활성화하여 RPC 호출 및 변수 복제 흐름을 추적할 수 있습니다.
  • ShowDebug: AI나 캐릭터의 네트워크 정보를 디버그 드로잉으로 표시할 수 있습니다. (예: showdebug net 또는 showdebug all)

리플리케이션은 멀티플레이어 게임 개발의 핵심이자 가장 복잡한 부분 중 하나입니다.

서버-클라이언트 모델과 각 클래스의 역할, 그리고 리플리케이션의 종류와 규칙을 명확히 이해하는 것이 중요합니다.

GAS(게임플레이 능력 시스템)를 사용하는 경우에도 동일한 원칙이 적용됩니다.

능력 실행 권한, 코스트/쿨다운 적용, 예측 보정 흐름은 9장 5절멀티플레이어 기준 실행 흐름과 함께 보면 구현 실수를 줄일 수 있습니다.


이번 절에서는 언리얼 엔진 블루프린트에서 리플리케이션이 어떻게 작동하며, 변수, 함수, 액터의 복제를 통해 게임의 상태와 이벤트를 네트워크를 통해 동기화하는 방법에 대해 알아보았습니다.

리플리케이션은 멀티플레이어 게임의 핵심이자 안정적인 게임플레이를 위한 필수 요소입니다.


리플리케이션은 변수 복제와 RPC 호출을 구분하고, 서버 권한과 소유권을 먼저 확인해야 안정적으로 동작합니다.

상태는 서버가 정하고 클라이언트는 복제본 검토

블루프린트 멀티플레이어에서 핵심은 서버 권한, 오너십, RepNotify, RPC 방향을 혼동하지 않는 것입니다.

  1. 서버 권한 판정

    Server 데미지, 아이템 획득, 위치 판정 같은 핵심 로직은 서버에서 실행합니다.

  2. 변수 복제

    Var Health, Ammo 같은 상태는 Replicated 또는 RepNotify로 동기화합니다.

  3. 이벤트 전달

    RPC 입력 요청, 이펙트 재생, 개인 알림은 RPC 방향을 맞춰 호출합니다.

  4. 클라이언트 반영

    Notify 복제된 값이 바뀌면 UI와 사운드, 이펙트를 갱신합니다.

  5. 호출 방향을 고르는 기준

    소유 클라이언트가 서버에 공격, 상호작용, 사용 요청을 보낼 때 씁니다. 서버가 모든 클라이언트에 폭발, 사운드, 연출을 퍼뜨릴 때 씁니다. 서버가 특정 플레이어에게만 알림이나 UI 피드백을 보낼 때 씁니다.

  6. Run on Server

    소유 클라이언트가 서버에 공격, 상호작용, 사용 요청을 보낼 때 씁니다.

  7. Multicast

    서버가 모든 클라이언트에 폭발, 사운드, 연출을 퍼뜨릴 때 씁니다.

  8. Owning Client

    서버가 특정 플레이어에게만 알림이나 UI 피드백을 보낼 때 씁니다.

멀티플레이 테스트에서는 역할별 화면, stat net, RPC 로그, 복제 변수 상태를 같은 순서로 확인해야 원인 추적이 빨라집니다.

복제 QA는 역할별 화면을 고정하고 같은 액션을 반복한다

변수가 안 보이는 문제와 RPC가 안 도는 문제는 역할을 나눠 보아야 구분된다.

역할 화면확인할 것대표 도구
Server진짜 상태 변경과 Run on Server 시작점Has Authority, log net
Owning Client입력, 예측 UI, 개인 피드백Is Locally Controlled
Simulated Client다른 플레이어 위치, 공개 이펙트, RepNotifyPlay As Client
Dedicated Server서버에서 불필요한 연출 노드가 돌지 않는지stat net

마지막으로 리플리케이션에서 서버 권한, 변수 복제, RPC 종류를 선택하는 기준을 정리합니다.

서버 권한과 RPC 방향을 먼저 고정한다

멀티플레이 블루프린트는 값 복제, RepNotify, Server RPC, Client RPC, NetMulticast가 어느 머신에서 실행되는지 분리해야 합니다.

  1. 서버는 게임 결과를 확정하고 클라이언트는 입력과 표현을 요청합니다

    체력, 점수, 아이템 획득처럼 판정이 필요한 값은 서버에서 바꾸고, 클라이언트는 소유 Pawn을 통해 요청만 보냅니다. 01 체력, 탄약, 점수처럼 상태 자체를 공유해야 하면 서버에서 Set하고 Replicated나 RepNotify로 변경 결과를 전달합니다. 02 공격 요청, 아이템 줍기, 문 열기처럼 클라이언트 입력이 서버 판정을 필요로 할 때 소유 Actor에서 호출합니다. 03 개별 HUD 알림은 Client RPC, 모두가 봐야 하는 Niagara나 사운드는 서버에서 NetMulticast로 보냅니다.

  2. 서버는 게임 결과를 확정하고 클라이언트는 입력과 표현을 요청합니다

    체력, 점수, 아이템 획득처럼 판정이 필요한 값은 서버에서 바꾸고, 클라이언트는 소유 Pawn을 통해 요청만 보냅니다.

  3. 변수 복제

    체력, 탄약, 점수처럼 상태 자체를 공유해야 하면 서버에서 Set하고 Replicated나 RepNotify로 변경 결과를 전달합니다.

  4. Server RPC

    공격 요청, 아이템 줍기, 문 열기처럼 클라이언트 입력이 서버 판정을 필요로 할 때 소유 Actor에서 호출합니다.

  5. Client와 Multicast

    개별 HUD 알림은 Client RPC, 모두가 봐야 하는 Niagara나 사운드는 서버에서 NetMulticast로 보냅니다.

블루프린트 리플리케이션은 복제 변수, RepNotify, RPC, 서버 권한 기준으로 점검합니다.