Advanced Replication and RPC

주상돈·2025년 4월 3일

TIL

목록 보기
47/53

대용량 데이터를 위한 효율적인 Replication 방안 및 RPC 구분 정리

아래는 대용량 데이터를 효율적으로 복제(Replication)하기 위한 방안과 RPC 사용 시 Reliable과 Unreliable의 차이에 대한 정리이다.


1. 대용량 데이터 복제의 문제점

  • 네트워크 패킷 크기 초과
    큰 배열이나 구조체를 한 번에 복제하면 네트워크 패킷의 크기 제한을 초과할 위험이 있다.

  • 과도한 대역폭 사용
    대용량 데이터를 한 번에 전송하면 불필요한 대역폭 소모로 인해 패킷 손실이나 지연이 발생할 수 있다.

  • 연결 끊김 위험
    최악의 경우, 한 번의 대용량 전송으로 연결이 끊길 위험이 있다.


2. FastArraySerializer

  • 목적
    큰 배열 전체를 매번 동기화하지 않고, 변경된 부분(델타)만 전송하는 방식으로 최적화한다.

  • 구현 방식

    • 배열의 각 요소는 FFastArraySerializerItem을 상속받아 구현한다.
    • 배열 자체는 FFastArraySerializer를 상속받아 사용한다.
  • 사용 예시
    인벤토리 목록이나 플레이어 명단처럼 아이템이 추가되거나 삭제, 일부만 변경되는 데이터를 효율적으로 동기화할 때 사용한다.

	// InventoryItem.h
	...
	struct FInventoryItem : public FFastArraySerializerItem
	{
	...
	void PreReplicatedRemove(const struct FInventoryArray& InArraySerializer);
	void PostReplicatedAdd(const struct FInventoryArray& InArraySerializer);
	void PostReplicatedChange(const struct FInventoryArray& InArraySerializer);
	....
	};

3. Replication 조건 (Replication Conditions)

데이터 전송 시 불필요한 대역폭 사용을 줄이기 위해, 특정 조건에서만 복제하도록 설정할 수 있다.

Condition설명사용 예시
COND_InitialOnly클라이언트가 처음 연결될 때 한 번만 초기 데이터 전송에 사용초기화에 필요한 대용량 Struct
COND_OwnerOnly해당 Actor의 소유자에게만 데이터를 전송특정 플레이어에게만 필요한 데이터
COND_SkipOwnerActor 소유자를 제외한 다른 클라이언트에게 전송다른 플레이어에게만 보여야 하는 정보
COND_AutonomousOnly자율적으로 제어되는 Actor에게만 전송자율 Actor에 필요한 데이터
COND_InitialOrOwner초기 패킷 또는 소유자에게 전송초기화와 소유자에게 모두 필요한 데이터
COND_Custom개발자가 동적으로 조건을 제어상황에 따라 복제 여부를 동적으로 결정해야 하는 경우

4. Chunking 및 Manual RPC Streaming

  • Chunking
    한 번에 전송할 데이터가 네트워크 한계를 초과하는 경우, 데이터를 여러 조각(Chunk)으로 나눠 전송한다.

  • Manual RPC Streaming
    Reliable RPC를 사용하여 데이터를 조각내어 보내고, 클라이언트에서 이를 재조립한다.
    단, 과도하게 사용하면 Reliable 버퍼가 가득 차는 문제가 발생할 수 있다.

  • 대체 방법
    Unreal Engine의 Replication System 바깥에서 소켓 통신이나 Online Subsystem의 파일 전송 기능 등을 사용한 후, 최종 상태만 간단히 동기화하는 방법도 고려할 수 있다.


5. Object Referencing 및 Dynamic Spawning

  • 데이터 참조 전송
    거대한 데이터를 직접 전송하는 대신, 데이터의 Reference나 ID만 전송하고 클라이언트에서 로컬에 저장된 프리셋 데이터를 활용하도록 한다.

  • 동적 스폰 (Dynamic Spawning)
    많은 하위 객체를 하나의 Actor에 넣는 대신, 여러 Actor나 컴포넌트로 분리하여 각각 복제하도록 설계한다.
    이렇게 하면 엔진이 필요에 따라 개별적으로 복제 여부를 판단할 수 있다.


6. Best Practices

  • 데이터 변경 빈도 및 대상 고려
    데이터가 얼마나 자주 변경되며, 어떤 클라이언트가 필요한지를 항상 고려하여 복제 방식을 결정한다.

  • 최적화 도구 활용
    Fast Array, 조건부 복제(Replication Conditions) 등 제공된 도구들을 활용하여 대용량 데이터 전송 시 CPU 부하와 대역폭 사용을 줄인다.

  • 배열 크기 제한 준수
    Unreal Engine에는 복제 가능한 배열의 크기에 기본 한계가 있으므로, 이 한계를 넘지 않도록 설계해야 한다.


7. Reliable vs Unreliable RPC

Reliable RPC

  • 특징
    반드시 전달되어야 하는 중요한 이벤트 전송에 사용된다.
    전송 보장 및 순서 보장이 있다.

  • 단점
    하나의 패킷이 유실되면 해당 RPC가 재전송될 때까지 이후에 전송된 다른 RPC들이 지연될 수 있다.
    과도하게 사용하면 네트워크 버퍼가 가득 차 연결에 영향을 줄 수 있다.

  • 사용 예시
    게임 시작/종료 알림, 플레이어 사망 이벤트, 중요한 아이템 획득, 퀘스트 완료 등

Unreliable RPC

  • 특징
    전달이 보장되지 않지만, 오버헤드가 적고 빈번한 업데이트에 적합하다.
    순서 보장은 기본 채널 내에서 유지되지만, 일부 메시지는 유실될 수 있다.

  • 사용 예시
    플레이어 위치 업데이트, 코스메틱 효과 등 빈번하게 발생하지만 손실되어도 큰 문제가 없는 이벤트

일반적인 사용 패턴

  • 기본적으로 모든 RPC는 Unreliable로 설정하고, 반드시 전달되어야 하는 중요한 이벤트에 한해서만 Reliable로 지정한다.
  • Client → Server RPC
    자주 발생하는 플레이어 입력(예: 움직임, 연속 발사 등)은 Unreliable로 처리한다.
    단, 중요한 입력(예: NPC 대화 선택 등)은 Reliable로 처리한다.
  • Server → Client RPC
    중요한 알림(예: 게임 오버, 큰 보상 획득)은 Reliable로, 빈번하지만 중요하지 않은 이벤트(예: 피격 피드백 효과)는 Unreliable로 처리한다.
  • Multicast RPC (Server → 모든 클라이언트)
    전역 이벤트의 경우, 빈번하지 않다면 Reliable Multicast를, 사소한 효과의 경우 Unreliable Multicast를 사용한다.

이와 같이 대용량 데이터를 효율적으로 복제하기 위해서는 데이터의 특성과 전송 빈도, 대상 클라이언트를 고려하여 적절한 도구와 조건을 적용하는 것이 중요하다. 또한, RPC 사용 시에는 중요한 이벤트에 한해서만 Reliable을 사용하고, 빈번한 업데이트에는 Unreliable을 사용하여 네트워크 부하를 최소화하는 설계가 필요하다.

0개의 댓글