실시간 데디케이티드 서버 핫픽스와 롤백 프로세스 설계 가이드
실시간 멀티플레이 서버를 무중단에 가깝게 핫픽스하고 장애 시 안전하게 롤백하는 절차를 배포 단위, 세션 드레이닝, 버전 호환성, 관측 지표 중심으로 정리합니다.

실시간 데디케이티드 서버의 핫픽스는 실행 중인 프로세스를 덮어쓰는 작업이 아니라 새 버전 인스턴스로 트래픽을 점진 전환하고 기존 매치를 안전하게 종료하는 배포 절차다. 롤백은 이전 컨테이너 이미지를 다시 띄우는 것만으로 충분하지 않으며 클라이언트 프로토콜·세션 상태·데이터 스키마의 하위 호환성을 함께 보장해야 한다.
실시간 게임 서버 핫픽스가 어려운 이유는 무엇인가?
HTTP 요청처럼 짧게 끝나는 서비스와 달리, 실시간 게임 서버는 하나의 프로세스가 수 분에서 수십 분 동안 매치 상태를 유지한다. 배포 중 프로세스를 즉시 종료하면 다음 문제가 발생한다.
- 진행 중인 매치가 강제 종료되어 패배 처리, 보상 누락, 이탈률 증가로 이어진다.
- 클라이언트와 서버의 프로토콜 버전이 달라져 패킷 파싱 또는 역직렬화에 실패한다.
- 신규 서버만 수정된 데이터 스키마를 전제로 하면 이전 버전으로 되돌릴 수 없다.
- 오류율만 보고 롤백하면 매치 종료율, 틱 지연, Redis 연결 수 같은 실시간 품질 저하를 놓칠 수 있다.
핫픽스의 목표는 세 가지다.
- 신규 매치는 수정된 빌드에만 배정한다.
- 기존 매치는 기존 빌드에서 정상 종료시킨다.
- 이상 징후가 확인되면 신규 배정을 즉시 이전 빌드로 되돌린다.

데디케이티드 서버 핫픽스 배포 단위를 어떻게 나눌까?
가장 관리하기 쉬운 단위는 불변 컨테이너 이미지다. 예를 들어 game-server:1.42.3을 운영 중이라면 핫픽스는 기존 태그를 교체하지 않고 game-server:1.42.4라는 새 이미지로 배포한다. 롤백 대상도 명확해진다.
| 구성 요소 | 핫픽스 원칙 | 롤백 시 확인 사항 |
|---|---|---|
| 게임 서버 바이너리 | 이미지 태그를 불변으로 관리 | 이전 이미지가 레지스트리에 보존됐는가 |
| 매치메이커 | 서버 버전별 가중치 라우팅 | 이전 버전을 다시 선택할 수 있는가 |
| 프로토콜 | 버전 필드와 선택적 필드 사용 | 이전 클라이언트·서버가 새 필드를 무시하는가 |
| DB 스키마 | Expand → Migrate → Contract | 이전 코드가 새 스키마를 읽고 쓸 수 있는가 |
| 설정 | 코드와 분리하고 버전 기록 | 잘못된 설정만 신속히 되돌릴 수 있는가 |
특히 데이터베이스 변경은 삭제나 이름 변경을 먼저 하면 안 된다. 예를 들어 player_rating을 mmr로 바꾸려면 새 컬럼을 추가하고 두 컬럼을 함께 기록한 뒤 모든 서버가 새 컬럼으로 전환된 뒤에 기존 컬럼을 제거한다. 이 방식이 롤백 가능한 확장-마이그레이션-정리 패턴이다.
핫픽스 절차: 신규 매치 전환과 세션 드레이닝
1. 배포 전 호환성 계약을 확인한다
서버는 연결 직후 protocolVersion, buildVersion, featureFlags를 교환해야 한다. 패킷에 필드를 추가할 때는 이전 서버가 모르는 필드를 무시할 수 있도록 설계하고 필수 필드의 의미를 기존 버전에서 바꾸지 않는다.
interface ClientHello {
protocolVersion: number;
buildVersion: string;
supportedFeatures: string[];
}
function canMatch(clientVersion: number, serverVersion: number) {
return clientVersion >= 7 && serverVersion >= 7;
}
실시간 전투 결과처럼 의미가 중요한 패킷은 단순한 버전 비교보다 기능 플래그가 안전하다. 예를 들어 damage-v2를 지원하지 않는 클라이언트와는 기존 피해 계산 결과 형식만 사용한다.
2. 새 인스턴스를 준비 상태로 검증한다
Kubernetes를 사용한다면 새 Pod가 시작됐다는 사실만으로 준비 완료로 판단하지 않는다. readinessProbe는 게임 데이터 로드, Redis 연결, 매치메이커 등록, 포트 바인딩까지 끝난 뒤에만 성공해야 한다.
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 3
failureThreshold: 3
/ready는 단순히 HTTP 200을 반환하는 엔드포인트가 아니라 다음 상태를 검사해야 한다.
- 필수 설정과 콘텐츠 데이터 로드 완료
- Redis, PostgreSQL 등 필수 의존성 연결 가능
- 서버 빌드와 프로토콜 버전 등록 완료
- 수용 가능한 매치 슬롯 존재
3. 카나리로 신규 매치만 점진 전환한다
처음부터 새 버전에 모든 매치를 보내지 않는다. 매치메이커에서 새 빌드의 가중치를 1~5%로 시작하고 지표가 안정적일 때만 25%, 50%, 100%로 확대한다. 이미 시작된 매치는 원래 인스턴스에 유지한다.
flowchart LR
A[새 서버 이미지 배포] --> B[준비 상태 검사]
B --> C[신규 매치 5% 카나리]
C --> D{지표 정상?}
D -- 예 --> E[가중치 확대]
E --> F[기존 서버 드레이닝]
D -- 아니오 --> G[신규 배정 중지]
G --> H[이전 버전으로 라우팅]
관측 시간은 최소한 평균 매치 길이보다 길어야 한다. 평균 매치가 12분이면 5% 카나리를 1~2분 보고 100%로 올리는 방식은 매치 종료 시점에만 드러나는 오류를 놓친다.
세션 드레이닝은 어떻게 구현할까?
드레이닝 상태의 서버는 새 매치를 받지 않되 현재 매치는 계속 처리한다. 매치메이커가 서버의 상태를 READY, DRAINING, TERMINATING처럼 명시적으로 관리하면 구현이 단순해진다.
READY : 신규 매치 배정 가능
DRAINING : 신규 매치 배정 금지, 기존 매치 유지
TERMINATING : 매치가 없거나 종료 기한 초과, 프로세스 종료 가능
드레이닝에는 최대 시간이 필요하다. 무한히 끝나지 않는 매치 때문에 오래된 버전을 영구 유지할 수 없기 때문이다. 예를 들어 drainDeadline = 30분을 두고 기한이 지나면 플레이어에게 재접속 안내를 보낸 뒤 매치 결과를 저장하고 종료한다. 강제 종료는 최후 수단이며 종료 이유를 분석 가능한 코드로 기록해야 한다.
동시 접속 수를 C, 평균 매치 시간을 T, 초당 새 매치 생성 수를 R이라고 하면 정상 상태에서 예상 활성 매치 수의 대략적인 상한은 다음처럼 잡을 수 있다.
이 값과 인스턴스당 수용량을 바탕으로 새 버전의 최소 여유 용량을 확보한 뒤 트래픽을 전환한다.
롤백은 어떤 조건에서 실행해야 하는가?
롤백은 배포 실패가 확인된 즉시 자동 또는 수동으로 실행할 수 있어야 한다. 다만 단일 지표의 순간 변동만으로 롤백하면 정상적인 피크 트래픽에도 흔들릴 수 있다. 배포 전 기준선과 비교한 복합 조건을 사용한다.
| 지표 | 예시 롤백 기준 | 의미 |
|---|---|---|
| 매치 생성 실패율 | 5분 평균 1% 초과 | 매치메이커 또는 서버 등록 문제 |
| 비정상 매치 종료율 | 기준선 대비 2배 이상 | 크래시, 예외, 연결 종료 문제 |
| 서버 틱 시간 p99 | 목표 틱의 120% 초과 | CPU 포화, 락 경합, GC 지연 |
| 패킷 처리 오류율 | 0.1% 초과 | 프로토콜 호환성 또는 역직렬화 오류 |
| 결과 저장 실패율 | 0.5% 초과 | DB 스키마, 트랜잭션, 권한 문제 |
예를 들어 20Hz 서버의 목표 틱 시간은 50ms다. p99 틱 시간이 60ms를 넘는 상태가 5분 지속된다면 롤백 또는 자동 확장 검토 대상이 된다.
롤백 시에는 새 버전 서버의 신규 매치 배정을 즉시 0으로 만들고 이전 버전 가중치를 100%로 복구한다. 새 버전에서 이미 시작한 매치는 호환성이 보장되는 한 종료까지 유지한다. 치명적인 데이터 손상이나 보안 문제가 있을 때만 해당 세션을 중단한다.
핫픽스와 롤백 체크리스트
배포 전
- 이미지 다이제스트와 Git 커밋 SHA를 릴리스 기록에 남겼다.
- 이전 서버와 클라이언트의 프로토콜 호환성을 검증했다.
- DB 변경이 하위 호환 가능한 확장 단계인지 확인했다.
- 카나리 비율, 관측 시간, 롤백 임계값을 정했다.
- 이전 이미지와 설정 버전이 즉시 배포 가능한 상태다.
배포 중
- 새 인스턴스의 준비 상태와 수용량을 확인했다.
- 신규 매치만 새 버전으로 점진 전환했다.
- 오류율뿐 아니라 틱 시간, 매치 종료율, 결과 저장 실패율을 관측했다.
- 기존 인스턴스를 드레이닝 상태로 전환했다.
롤백 후
- 신규 배정이 이전 버전으로 완전히 돌아왔는지 확인했다.
- 새 버전에서 발생한 오류를 빌드 버전, 리전, 맵, 게임 모드별로 분류했다.
- 중복 보상 또는 결과 누락이 없는지 재처리 큐를 점검했다.
- 다음 배포 전에 재현 테스트와 회귀 테스트를 추가했다.
자주 묻는 질문 (FAQ)
서버 바이너리를 실행 중에 교체하면 안 되나요?
권장하지 않는다. 실행 중인 메모리 상태와 네트워크 연결의 일관성을 보장하기 어렵다. 새 인스턴스를 띄우고 매치메이커 라우팅을 전환하는 방식이 안전하다.
롤백할 때 이미 새 버전에서 시작한 매치는 어떻게 하나요?
프로토콜과 저장 포맷이 호환된다면 해당 매치는 새 버전에서 끝까지 실행한다. 신규 매치만 이전 버전으로 되돌리는 것이 일반적이다. 데이터 손상이나 보안 사고가 확인된 경우에만 중단 절차를 별도로 적용한다.
블루그린 배포와 카나리 배포 중 무엇이 더 적합한가요?
롤백 속도가 최우선이고 충분한 여유 인프라가 있다면 블루그린이 단순하다. 실시간 품질 지표를 보며 위험을 줄이고 싶다면 신규 매치 가중치를 조절하는 카나리 배포가 더 적합하다.
정리
안전한 실시간 서버 핫픽스의 핵심은 불변 빌드, 버전 호환성, 신규 매치 라우팅 분리, 세션 드레이닝, 지표 기반 롤백이다. 배포 자동화보다 먼저 이 다섯 가지 계약을 운영 절차로 고정하면 긴급 수정도 플레이어 경험과 데이터 정합성을 훼손하지 않고 처리할 수 있다.



