공간 handoff는 상태 복사 문제가 아니라 권위 있는 쓰기 주체를 한 세대에서 다음 세대로 바꾸는 문제입니다. snapshot을 준비했다는 응답과 실제로 새 owner·epoch를 내구 커밋한 순간을 분리하고, 입력·라우팅·전투 효과가 그 전환점을 기준으로 판단하도록 해야 양쪽 서버의 동시 처리를 막을 수 있습니다.
상태 복사와 Owner 권위의 분리
server A의 캐릭터를 B로 복사한 뒤 A와 B가 모두 공격과 보상을 처리하면 중복 효과가 생깁니다. handoff ID는 이번 권위 이전을 식별하고, owner epoch는 소유자 세대를 나타내며 단조롭게 증가합니다. B가 snapshot(한 시점의 상태 복사본)을 받아 예정된 다음 epoch를 준비하는 일과, 그 epoch를 내구 상태에 커밋해 권위를 B로 넘기는 일은 분리합니다. 관찰 replica는 근처 상태를 볼 수 있어도 공격·보상 같은 권위 쓰기 경로가 아닙니다.
마지막 입력·Delta 이후의 권위 전환점
| 단계 | 보존할 사실 |
|---|---|
| 준비 | B의 snapshot·예정 epoch g+1 |
| 유입 정리 | A의 신규 입력 차단·처리 중 drain |
| 최종 반영 | 마지막 delta·lastAppliedInput·event 위치 |
| 권위 commit | 내구 owner B,g+1·handoff state |
| routing | router의 새 owner/epoch·stale cache 처리 |
| 완료 | old 접근 정리·보류 입력·대사 |
전환 구간에 들어오면 입력을 잠시 보류하는 방식이 가장 단순합니다. 무중단으로 입력을 계속 받으려면 크기가 제한된 bounded buffer(임시 입력 저장 공간)에 handoff ID와 sequence(입력 순서 번호)를 함께 기록합니다. 최종 상태에 기록된 lastAppliedInput(마지막 적용 입력)까지의 연속된 적용 구간(prefix) 뒤에 있는 입력만 처리하고, 각 입력은 한 번만 처리합니다. 예를 들어 A가 owner=A,epoch=4,lastApplied=120을 기록한 뒤 B가 snapshot과 입력 121까지 준비했지만 ACK가 유실됐다고 합시다. 재시도는 새 handoff를 만들지 않고 handoff ID와 epoch 5 상태를 조회해 121의 적용 여부를 확인합니다. cutover commit이 없으면 A가 계속 유효하고, commit이 있으면 A의 epoch 4 쓰기는 거절되며 B의 epoch 5 prefix 뒤에서만 재개해야 합니다.
ACK가 유실돼도 성공했다고 추측하지 말고 같은 handoff 상태를 조회해 마지막 적용 지점 뒤부터 재개합니다.
그림을 글로 읽기
- A · 현재 owner g
- B 준비 · snapshot g+1 후보
- A drain·마지막 delta/input
- 내구 cutover · owner B,g+1
- 새 routing·옛 epoch 쓰기 거절
- A · 현재 owner g → B 준비 · snapshot g+1 후보: 상태 복사
- B 준비 · snapshot g+1 후보 → A drain·마지막 delta/input: 준비 확인
- A drain·마지막 delta/input → 내구 cutover · owner B,g+1: 최종 반영 확인
- 내구 cutover · owner B,g+1 → 새 routing·옛 epoch 쓰기 거절: 권위 전환점
Fencing과 저장 경계의 권위 검증
A가 “아직 owner”를 확인한 뒤 멈췄다가 cutover 후 쓰면 사전 조회만으로 막지 못합니다. 실제 state/event/보상 저장이 expected epoch를 원자 검사해야 합니다. router cache에는 owner와 epoch를 같이 저장하고 mismatch면 재조회합니다. stable account/character와 권리 key를 유지해 handoff마다 보상을 새로 만들지 않습니다.
cutover 전 B 실패면 A 유지 또는 조정자 재개 정책을, cutover 후 실패면 이미 바뀐 권위를 기준으로 복구를 정합니다. A가 drain 중 죽었다면 기록된 prefix·원장으로 미확인 입력을 찾아 재전달하되 dedup합니다. 단순 timeout을 근거로 양쪽을 owner로 살리지 않습니다.
경계 전투의 단일 피해·보상 확정 경로
공격자가 A 서버에 있고 대상이 B 서버에 있을 때, 두 서버가 서로 다른 현재 snapshot(판정에 쓰는 상태 복사본)을 읽고 각각 피해를 확정하면 중복·모순이 생깁니다. 공격 ID, 기준 tick, 양쪽 state/history snapshot, handoff epoch와 피해를 최종 확정할 owner를 정합니다. 공유 판정 영역을 사용하거나 읽기용 snapshot을 조합하더라도 피해·보상 효과를 생성하는 권위 경로는 하나로 제한합니다.
공격이 늦게 도착하면 기록된 tick과 rewind 정책으로 검증한 뒤, 그 공격을 현재 대상 세대와 상태에 적용합니다. 관찰 replica는 damage를 직접 쓰지 않고, 과거 hitbox snapshot(충돌 판정 영역의 상태)의 체력을 현재 state에 덮어쓰지도 않습니다. 같은 공격의 재전달과 서로 다른 접촉은 안정 ID로 구분해 중복 재처리와 별개의 접촉을 혼동하지 않습니다.
경계 Hysteresis와 권위 중복의 분리
경계 왕복 때 매틱 이동을 줄이기 위해 완충 구간·최소 유지 시간을 둘 수 있습니다. 폭이 커지면 한 server 부하와 관찰 범위도 커져 입력 보류·handoff 반복률·p99를 비교합니다. 언제나 유효 writer는 계약된 하나여야 합니다.
준비/ACK 전후 crash·늦은 delta·옛 router·경계 전투·접속 종료·보상 event·옛 epoch 쓰기를 시험합니다. 재현 연습에서는 준비 ACK 전, drain 중, cutover commit 직후, 옛 router cache 사용 시점을 각각 중단합니다. 매 경우 저장소에 유효 writer가 하나만 남고, 입력 sequence는 lastApplied 뒤에서만 재개되며, 동일 attack ID의 피해·보상 effect가 한 번만 확정되는지를 확인합니다. 실제 게임 서버의 tick·rewind·네트워크 지연 수치는 이 설계만으로 검증되지 않습니다.
이 노트는 권위 이전 설계이며 실제 분산 게임 server handoff를 실행한 결과는 아닙니다.