1:07 · client prediction · server authority · reconciliation · netcode

앞으로 달렸는데, 왜 뒤로 끌려갈까?

이 영상은 MMO에서 캐릭터가 앞으로 달리다 뒤로 끌려가는 러버밴딩이 왜 생기는지 보여 준다. 클라이언트는 입력 즉시 캐릭터를 움직이고 서버가 나중에 그 이동을 판정하는데, 둘의 결과가 어긋나면 서버 쪽 위치로 되돌려진다. 원인은 네트워크 지연과 서버·클라 상태 불일치 두 갈래이고, 완전히 없앨 수는 없지만 덜 생기고 덜 보이게 만들 수 있다.

01러버밴딩이란

내 캐릭터가 서버가 인정한 위치로 끌려 돌아가는 현상 · ▶ 이 장면 보기

0m부터 50m까지 눈금이 있는 길 위에 두 개의 점이 있다. 꽉 찬 점은 "클라 화면"의 내 캐릭터이고, 점선 원은 "서버 판정" 위치다. 처음에는 서버 위치가 클라를 살짝 뒤에서 따라오는데, 어느 순간 서버 점이 멈추고 "서버: 여기서 이동 인정 멈춤" 칩이 뜬다.

클라 점은 그 뒤로도 계속 달리다가 "↩ 보정 · 뒤로 끌려감" 표시와 함께 서버 점 위치로 튕기듯 되돌아간다. 그 다음 두 점이 다시 같이 움직인다.

화면 문구는 "앞으로 달렸는데 뒤로 끌려가는 현상 = 러버밴딩", "내 화면(클라)의 위치와 서버가 인정한 위치가 벌어졌다가, 서버 쪽으로 되돌려질 때 생깁니다"다. 게임 서버가 위치의 최종 권한을 갖고 있기 때문에 생기는 현상이다.

02예측과 판정

클라는 먼저 움직이고, 서버가 나중에 맞는지 판정합니다 · ▶ 이 장면 보기

위 레인은 Client("입력 즉시 이동 (예측)"), 아래 레인은 Server("받은 입력 검증 → 확정")이고 가로축은 시간이다. 클라가 Move #1부터 Move #6까지 이동 입력을 차례로 보내고, 서버는 각각을 검증한 뒤 Ack #1~Ack #5로 응답한다. 첫 왕복 구간에는 RTT 표시가 붙는다. 입력을 보낸 뒤 판정이 돌아오기까지 최소 한 번의 왕복 시간이 걸린다.

클라는 Ack를 기다리지 않고 먼저 움직인다. 기다리면 모든 조작이 RTT만큼 늦게 반응하기 때문이다. 이렇게 서버 결과를 예상해 먼저 반영하는 것을 클라이언트 예측이라 한다.

마지막 Move #6에는 Ack 대신 빨간 Correction #6이 돌아오고, 클라 쪽에 "↩ 위치 되돌림"이 뜬다. 아래 문구가 두 경우를 정리한다.

03원인 ① 네트워크

입력이 늦거나 사라지면 서버의 캐릭터는 멈춰 있습니다 · ▶ 이 장면 보기

Client와 Server 사이로 이동 패킷이 일정 간격으로 흘러가다가, 중간에 패킷들이 길 위에서 멈추고 일부는 빨갛게 떨어진다. "정체 · 손실 · 재전송 대기" 칩과 함께 원인 세 가지가 붙는다. 지연 스파이크, 패킷 손실, TCP 재전송 대기(Head-of-Line)다.

오른쪽 RTT (ms) 그래프는 평소 60ms 안팎에서 순간적으로 800ms대까지 치솟았다가 내려온다. TCP는 순서를 보장하기 때문에 앞 패킷 하나가 손실되면 재전송될 때까지 뒤에 도착한 패킷도 애플리케이션에 전달되지 않는다. 손실 하나가 그 뒤 입력 전체의 지연으로 번지는 이유다.

아래 레인에서 클라 캐릭터는 계속 달리지만 서버 캐릭터는 제자리에 서 있다가, 결국 클라가 서버 위치로 되돌려진다. 화면 문구는 "입력이 안 오는 동안 서버의 캐릭터는 제자리", "서버 정책에 따라 늦게 몰려온 입력은 거부되거나 잘린다 → 서버 위치로 되돌림"이다.

04원인 ② 판정 불일치

네트워크가 멀쩡해도, 서버와 클라가 아는 상태가 다르면 생깁니다 · ▶ 이 장면 보기

네트워크가 정상이어도 서버와 클라가 알고 있는 상태가 다르면 판정이 어긋난다. 화면은 네 칸으로 나뉘어 각 사례를 반복 재생한다.

네 경우 모두 클라 점이 먼저 나가고 서버 점이 뒤에 남았다가 클라가 끌려온다는 모양은 같다. 03과 달리 패킷은 제때 도착했고, 어긋난 것은 판정에 쓰인 상태다.

05줄이는 방법

완전히 없앨 순 없지만, 덜 생기고 덜 보이게 · ▶ 이 장면 보기

위쪽 패널은 같은 보정을 두 방식으로 처리한 결과를 나란히 보여 준다. "즉시 스냅"(보정 위치로 순간이동) 레인에서는 Correction을 받을 때마다 캐릭터가 뒤로 튄다. "재조정 + 스무딩"(미확인 입력 재적용 후 보간) 레인에서는 같은 보정을 받아도 실제 오차만큼만 부드럽게 밀린다.

차이는 서버가 보내 준 위치가 이미 과거 시점이라는 데서 나온다. 즉시 스냅은 그 과거 위치로 바로 옮기니 그 사이에 입력한 이동까지 사라진다. 재조정은 보정 위치에서 아직 Ack를 받지 못한 입력을 다시 적용해 현재 위치를 다시 계산한다.

아래에는 줄이는 방법 여섯 가지가 체크된다.

시퀀스 번호 · 재조정 · 보간은 클라 쪽, 오차 허용치는 서버 쪽에서 보정 자체를 줄인다. 뒤의 둘은 03과 04의 원인을 줄이는 방법이다.

이 영상에 나온 용어는 용어집에 정리했다.