[DAY69] Network Optimization : RepNotify, Frequency, Dormancy

베리투스·2025년 11월 24일

TIL: Today I Learned

목록 보기
59/93

지금까지는 "데이터를 어떻게 보낼까?"를 고민했다면, 오늘은 "어떻게 효율적으로 보낼까?"를 배웠다. 변수가 바뀔 때만 로직을 실행하는 RepNotify, 전송 빈도를 조절하는 Frequency, 변하지 않는 액터를 잠재우는 Dormancy까지. 네트워크 대역폭과 CPU를 아끼는 최적화 3대장을 정리했다.


📌 오늘의 목표

  • RepNotify (OnRep_)의 작동 원리와 서버 수동 호출의 필요성 이해
  • NetUpdateFrequency를 조절하고 클라이언트에서 보간(Lerp) 처리하기
  • NetDormancy를 통해 변경이 없는 액터의 네트워크 연산 끄기

📚이론 및 원리

1. 값이 바뀔 때만 움직여라 : RepNotify

기존에는 Tick 함수에서 매번 변수 값을 확인해서 로직을 처리했다. 하지만 문이 열리고 닫히는 것처럼 가끔 일어나는 일을 매 프레임 검사하는 건 낭비다.
언리얼은 "서버에서 값이 바뀌어 클라이언트에 도착하는 순간" 자동으로 호출되는 콜백 함수 기능인 RepNotify를 제공한다.

  • 주의할 점:
    • 블루프린트의 RepNotify는 서버에서도 자동 실행되지만, C++의 OnRep_ 함수는 오직 클라이언트에서만 자동 호출된다.
    • 따라서 서버에서도 불이 켜지거나 문이 열리는 시각적 효과를 보고 싶다면, 값을 변경한 직후에 서버가 직접 함수를 호출해줘야 한다.
// [ADXBox.h]
// 변수가 복제되어 도착하면 OnRep_ServerLightColor 함수가 자동 실행됨
UPROPERTY(ReplicatedUsing = OnRep_ServerLightColor)
FLinearColor ServerLightColor;

UFUNCTION()
void OnRep_ServerLightColor();

// [ADXBox.cpp]
void ADXBox::ChangeColor()
{
    if (HasAuthority())
    {
        // 1. 데이터 변경 (클라이언트는 잠시 후 OnRep이 자동 실행됨)
        ServerLightColor = FLinearColor::MakeRandomColor();
        
        // 2. 서버는 OnRep이 자동 실행되지 않으므로, 직접 호출해야 함
        OnRep_ServerLightColor(); 
    }
}

void ADXBox::OnRep_ServerLightColor()
{
    // 변경된 색상을 실제 메시에 적용 (시각적 처리)
    PointLight->SetLightColor(ServerLightColor);
}

2. 전송 횟수 줄이기 : NetUpdateFrequency

모든 액터가 1초에 100번씩(기본값) 상태를 업데이트할 필요는 없다. 멀리 있는 배경 물체나 아이템 상자 같은 건 빈도를 확 낮춰도 된다.

  • 전략:
    • NetUpdateFrequency를 낮춘다 (예: 100Hz \rightarrow 1Hz).
    • 이렇게 하면 통신량은 줄지만 움직임이 뚝뚝 끊겨 보인다.
    • 클라이언트의 Tick에서 보간(Interpolation/Lerp) 처리를 해주면 부드럽게 보인다.
// 생성자에서 빈도 설정 (1초에 1번만 동기화 시도)
SetNetUpdateFrequency(1.0f); 

// Tick에서 보간 처리
void ADXBox::Tick(float DeltaSeconds)
{
    if (!HasAuthority()) 
    {
        // 현재 위치와 서버에서 받은 목표 위치 사이를 부드럽게 이동 (Lerp)
        CurrentLocation = FMath::Lerp(CurrentLocation, ServerLocation, Alpha);
        SetActorLocation(CurrentLocation);
    }
}

3. 변하지 않으면 잠들어라 : NetDormancy (휴면)

아무리 빈도를 낮춰도, 서버는 "혹시 변한 거 없나?" 하고 계속 감시(Polling)를 한다. 만약 게임 시작 후 색상이 딱 한 번 바뀌고 영원히 안 바뀌는 상자가 있다면?
이럴 땐 아예 네트워크 연결을 끊은 것처럼 잠재우는 Dormancy(휴면) 기술을 쓴다.

  • DORM_Initial: 처음에만 동기화하고 바로 잠든다.
  • FlushNetDormancy: 잠든 액터를 강제로 깨워서 업데이트한다.
  • Conditional Replication: DOREPLIFETIME_CONDITION을 쓰면 특정 조건(예: 처음 한 번만 COND_InitialOnly)일 때만 데이터를 보낼 수 있어 대역폭을 더 아낄 수 있다.
// 생성자: 시작하자마자 휴면 상태로 설정 (CPU 절약)
SetNetDormancy(DORM_Initial);

// 게임 도중 색상을 바꿀 일이 생기면?
if (HasAuthority())
{
    ServerLightColor = NewColor;
    
    // 강제로 깨워서 동기화 수행
    FlushNetDormancy(); 
}

✅ 핵심 요약

개념설명핵심 포인트
RepNotify변수 수신 시 함수 자동 실행서버는 자동 실행 안 됨 (수동 호출 필수)
NetUpdateFrequency초당 동기화 시도 횟수낮추면 대역폭 절약, 보간(Lerp) 필요
NetDormancy액터를 네트워크 휴면 상태로 만듦데이터 변경 시 FlushNetDormancy로 깨워야 함
Conditional Rep특정 조건에서만 변수 복제DOREPLIFETIME_CONDITION 사용
profile
Shin Ji Yong // Unreal Engine 5 공부중입니다~

0개의 댓글