언리얼 멀티플레이 - Client-Side Prediction

yys·2026년 8월 4일

TIL

목록 보기
79/85

Client-Side Prediction


이번에는 멀티플레이어 게임에서 클라이언트의 반응성을 높이기 위해 사용하는 Client-Side Prediction을 알아보려고 한다.

탄약처럼 게임플레이에 영향을 주는 값은 서버가 관리해야 한다.

만약 클라이언트가 탄약의 최종 값을 결정할 수 있다면 자신의 탄약을 임의로 증가시키거나, 탄약이 없는 상태에서도 계속 발사할 수 있다.

따라서 기본적인 탄약 처리 흐름은 다음과 같다.

발사 입력 → Server RPC → Server Ammo 감소 → Client에 결과 전달

하지만 모든 결과를 서버에서 처리한 뒤 클라이언트에 전달하면 네트워크 지연 때문에 발사와 화면의 반응 사이에 차이가 발생한다.

예시를 들어보자.
먼저 클라가 총알이 10개 들어있는 총을 한 발 쐈다고 가정해보자

일반 Replication 기준으로 판단한다면, 서버는 이를 받고 값이 올바른지 검증한다.

이후 클라는 서버로부터 복제된 값을 받는다.
이 하나의 과정을 처리하는 데 걸리는 시간을 RTT라고 한다.

다만 이 RTT가 처리되는 과정에서 또 다른 클라 입력이 들어오면 다음과 같이 된다.

클라는 최종 총알 수가 8에서 미동이 없어야 하지만, 9 -> 8 -> 9 -> 8처럼 핑퐁되는 현상이 발생한다.

이를 방지하기 위해 사용하는 것이 바로 Client-Side Prediction인데, 이는 서버의 응답을 기다리기 전에 클라이언트가 결과를 먼저 예측하고, 이후 서버의 값이 도착하면 차이를 보정하는 방식이다.

Sequence


이번 구현에서는 Sequence를 사용해 서버가 아직 처리하지 못한 로컬 발사 수를 추적한다.

이름은 Sequence지만, 일반적인 패킷 순서 번호보다는 서버 응답을 받지 못한 예측 발사의 개수에 가깝다.

로컬에서 발사할 때마다 다음 처리를 실행한다.

  • Ammo 감소
  • Sequence 증가

서버의 발사 결과가 하나 도착하면 다음 처리를 실행한다.

  • 서버의 AuthAmmo 적용
  • Sequence 감소
  • 남아 있는 Sequence만큼 Ammo 추가 감소

핵심 관계는 다음과 같다.

보정된 Ammo = Server Ammo - 아직 응답받지 못한 발사 수

서버가 전달한 값에는 서버가 현재까지 처리한 발사만 반영되어 있다.

그 이후 클라이언트가 추가로 예측한 발사는 아직 서버 값에 포함되지 않았으므로, 남아 있는 Sequence만큼 다시 감소시켜야 한다.

Client-Side Prediction 예시


위의 정의를
탄약이 10발이고 Sequence가 0인 상태에서 빠르게 두 발을 발사한다고 가정해보자.

첫 번째 로컬 발사가 실행된다.

서버의 응답을 기다리지 않고 두 번째 발사도 실행한다.

이후 서버가 첫 번째 발사를 처리하고 권위 탄약인 9를 전달한다.
이때, Replication으로 전달하지 않는다는 점을 유의해야 한다. 전달하는 방식은 RPC로 전달해준다.

클라이언트는 응답을 받은 발사 하나를 Sequence에서 제거한다.

서버의 값은 9지만, 아직 서버 응답을 받지 못한 두 번째 발사가 하나 남아 있다.

따라서 9 - 1을 계산하면 화면의 탄약은 기존 값인 8을 유지한다.

이후 두 번째 서버 응답이 도착한다.

모든 발사에 대한 응답을 받았으므로 Sequence는 다시 0이 되고, 클라이언트와 서버의 탄약은 8로 일치한다.

서버 응답이 늦게 도착하더라도 화면의 탄약은 10 → 9 → 8로만 감소한다.

Prediction과 Reconciliation


Client-Side Prediction은 크게 두 단계로 나눌 수 있다.

Prediction


클라이언트가 서버의 응답을 기다리지 않고 결과를 먼저 적용하는 단계이다.

이번 구현에서는 발사하는 순간 로컬 Ammo를 감소시키고 Sequence를 증가시킨다.

이를 통해 플레이어는 네트워크 지연과 관계없이 즉각적인 반응을 확인할 수 있다.

Reconciliation


서버의 권위 값이 도착하면 클라이언트의 예측 결과를 다시 맞추는 단계이다.

서버 값을 그대로 사용하는 것이 아니라, 서버가 아직 처리하지 못한 로컬 발사 수를 함께 반영한다.

예측이 정확했다면 화면의 값은 변하지 않고 서버 값에 자연스럽게 수렴한다.

예측 결과와 서버 결과가 다르다면 서버의 권위 값을 기준으로 수정된다.

즉, 클라이언트는 결과를 먼저 보여줄 수 있지만 최종 결정권은 서버가 유지한다.

Client-Side Prediction의 범위


클라이언트는 발사 순간 탄약을 먼저 감소시키지만, 최종적으로는 서버가 전달한 AuthAmmo를 기준으로 값을 보정한다.

다만 이 구조가 클라이언트에서 계산한 적중 결과까지 검증해주는 것은 아니다.

이번 발사 시스템은 클라이언트가 계산한 FHitResult를 서버에 전달하며, 서버 재트레이스나 Server-Side Rewind는 별도의 문제이다.

두 기술의 목적은 다음과 같이 다르다.

  • Client-Side Prediction : 탄약처럼 지연이 보이는 상태를 먼저 예측하고 보정
  • Server-Side Rewind : 지연된 적중 판정을 과거 위치를 기준으로 재검증

둘 다 네트워크 지연을 다루지만 해결하려는 대상은 다르다.

profile
게임 개발 지망생

0개의 댓글