📌 온라인 게임에서의 네트워크 동기화 방식
온라인 게임은 장르를 떠나, 크게 보면 Sync(동기, 실시간)와 ASync(비동기)로 나눌 수 있으며
Sync는 온라인 서버(클라우드)환경과 LAN 파티 환경으로 나뉜다.
1️⃣ Sync
동기 방식은 모든 클라이언트가 일정한 주기로 같은 데이터를 공유하며 동기화하는 방식이다.
네트워크에서 클라이언트와 서버 간의 데이터가 일정한 타이밍에 맞춰 동기화되므로, 모든 플레이어가 같은 게임 상태를 유지할 수 있다.
빠른 응답보다는 정확한 데이터 동기화가 중요한 경우에 사용.
🟢 장점
- 완벽한 동기화 → 모든 클라이언트가 동일한 게임 상태를 유지함
- 예측 가능 → 프레임별로 데이터가 동기화되므로, 결과가 예측 가능함
- 일관성 유지 → 멀티플레이 환경에서 모든 유저가 동일한 정보를 받음
🔴 단점
- 지연 시간 증가 → 서버와 클라이언트가 주기적으로 데이터를 교환해야 하므로 네트워크 지연이 클 수 있음
- 패킷 손실 시 문제 발생 → 동기화된 데이터를 받지 못하면 게임 플레이에 지장이 생김
- 리소스 부담 → 실시간으로 모든 데이터를 동기화해야 하므로 서버 및 네트워크 부하가 증가
2️⃣ Async
비동기 방식은 각 클라이언트가 독립적으로 데이터를 처리하고 필요할 때만 데이터를 주고받는 방식이다.
클라이언트가 서버의 응답을 기다리지 않고 자체적으로 로컬 데이터를 처리하고, 특정 시점에 동기화를 수행한다.
빠른 응답이 중요하며, 일정 수준의 오차를 허용할 수 있는 경우 사용.
🟢 장점
- 빠른 반응 속도 → 클라이언트가 서버 응답을 기다리지 않고 즉시 처리 가능
- 네트워크 부하 감소 → 모든 프레임마다 데이터를 주고받지 않으므로 트래픽이 줄어듦
- 패킷 손실 영향이 적음 → 지속적인 동기화가 필요하지 않아 일시적인 네트워크 문제에도 강함
🔴 단점
- 데이터 불일치 가능성 → 클라이언트가 로컬에서 처리한 결과가 서버 데이터와 다를 수 있음
- 해킹 및 치트에 취약 → 클라이언트가 데이터를 자체적으로 처리하므로 보안 문제가 발생할 수 있음
- 복잡한 보정(Interpolation, Reconciliation) 필요 → 서버와 클라이언트 간 데이터 불일치를 보정해야 함
🔔 정리
대부분 온라인 게임은 완전한 Sync방식이나 Async방식을 하나 택해서 사용하지 않고, 두 방식을 적절히 조합하는 하이브리드 방식을 사용한다.
반응 속도가 중요한 요소는 비동기인 Async, 게임의 핵심 데이터는 Sync 방식으로 처리하여 네트워크 성능과 데이터의 일관성을 모두 확보하는 등 게임의 장르와 특성에 맞게 동기화 방식을 조합해 네트워크 구조를 설계하는 것이 핵심이다.
🎮 FPS 게임 (Call of Duty, Valorant 등)
- 플레이어의 움직임은 Async 방식으로 처리하여 빠르게 반영
- 총을 쏘는 동작과 피격 판정은 서버에서 검증하여 Sync 방식으로 처리
🎮 MOBA 게임 (League of Legends, Dota 2 등)
- 이동과 기본 공격은 ASync 방식으로 처리
- 스킬 판정과 충돌 판정은 Sync 방식으로 처리
📌 CAP 이론
네트워크 분산 시스템의 동기화에서 "동시에 만족시킬 수 없는 세 가지 요소"를 정의한 이론이다.
이 이론은 2000년 Eric Brewer가 발표했으며, 이후 분산 데이터베이스 및 네트워크 시스템을 설계할 때 중요한 기준이 되었다.
분산 시스템에서 Consistency(일관성), Availability(가용성), Partition Tolerance(네트워크 분할 허용성) 이렇게 세 가지 속성을 정의하며, 이 세 가지를 모두 동시에 만족할 수 없고, 두 가지만 선택해야 한다는 원칙을 제시했다.
1️⃣ Consistency(일관성)
- 모든 노드가 동일한 데이터를 유지해야 한다.
- 어느 노드에서 데이터를 읽더라도 같은 결과가 나와야함
2️⃣ Abailability(가용성)
- 시스템이 항상 요청을 처리할 수 있어야 한다.
- 일부 노드에 장애가 발생하더라도 시스템이 계속 동작해야 함
3️⃣ Partition Tolerance(네트워크 분할 허용성)
- 시스템을 분할하여 병렬처리 등을 하여, 네트워크 장애가 발생해도 시스템이 계속 동작할 수 있어야 한다.
- 일부 노드 간 통신이 끊어지더라도 시스템이 정상적으로 동작해야 함
📌 CAP 이론에 따른 분산 시스템의 선택
CAP 이론에 따르면 세 가지 속성을 동시에 만족할 수 없으므로, 두 가지만 선택해야 한다.
이로 인해 분산 시스템은 보통 CP, AP 중 하나의 조합을 선택하게 된다.
✅ CP(일관성 + 네트워크 분할 허용성) 설계
초기 온라인 게임은 "일관성"을 유지하고 "가용성"을 포기했다.
사용자의 입력을 바로 서버로 보내, 일정시간(Tick) 마다 클라이언트로 브로드캐스팅하여 수신 받은 이벤트로 게임 클라이언트의 상태를 업데이트 하는 방식을 사용했다.
A클라이언트가 이벤트를 RPC로 보내면 서버는 모든 이벤트를 모아두었다가 일정 Tick마다 브로드캐스팅 하여 전체 클라이언트에 업데이트한다. 이는 빠른 반응속도가 필요 없을 때 비교적 쉽게 구현이 가능했다.
가용성을 포기하고 일관성을 우선으로하는, CP 설계의 대표적인 게임이 스타크래프트이다.
게이머가 마린을 우클릭하여 이동시켰다고 가정을 해본다면
1️⃣ 마우스 우클릭
2️⃣ 클라이언트가 캐릭터 이동 이벤트를 서버에 전송
3️⃣ 서버에서 브로드캐스팅한 데이터로, 클라이언트가 상태를 업데이트
플레이어가 입력한 이벤트 시간과 서버에서 오는 데이터를 수신하는 시간 간의 Gap이 발생하게 된다.
그래서 예전의 게임들은 클라이언트 업데이트 이전에 플레이어에게 사운드 이펙트, UI 등으로 게이머에게 피드백을 하여 마치 기다리는 시간이 없는 것처럼 위장하였다.
✅ AP(가용성 + 네트워크 분할 허용성) 설계
이후 다수의 사용자가 게임을 동시에 실행하는 MMO, FPS, Sports 와 같이 반응성이 우선인 게임 장르가 대거 등장했고, 이 게임 장르들은 기본적인 캐릭터 이동은 Tick을 짧게 브로드캐스팅하고, 실시간으로 별도의 채널을 통해 다중 브로드 캐스팅 방식으로 진화해 왔다.
반응성이 중요한 게임에서 많이 사용되는데,
A 클라이언트가 이벤트를 발생시켰을 때, 컨트롤 하고 있는 A 클라이언트를 먼저 예측 업데이트하고 RPC에 이벤트를 보내면 즉시 다른 클라이언트에도 브로드캐스팅하여 업데이트한다.
이때 A는 이미 예측하여 업데이트를 마친 상태이고, 서버로 부터 받은 데이터로 예측되어 업데이트 된 것이 맞으면 예측한 데이터를 그대로 사용하고, 틀리다면 이전 상태로 롤백하는 등의 검증과 보정이 이루어진다.
최근에 등장하는 게임들은 일관성을 포기하고 가용성을 우선으로 하는 AP 설계를 바탕으로 이루어진 것이 많다.
게임 클라이언트를 우선 업데이트하고, 후에 일관성을 보정하는 방법을 사용한다.
이 때문에 응답속도(Latancy)가 낮을 경우, 게임을 하다 보면 뒤에 잘 숨었는데 뒤늦게 죽는 경우, 갑자기 캐릭터가 이상한 방향으로 가는 경우 등이 발생한다.
1️⃣ 클라이언트에서 이동 입력 감지 ➡️ 클라이언트에서 즉시 예측(Prediction) 이동 업데이트
2️⃣ RPC를 통해 이동 이벤트 서버에 전송
3️⃣ 서버에서 이동 검증 후 전체 브로드캐스팅
4️⃣ 클라이언트에서 서버 데이터와 비교하여 보정(Reconciliation) 수행 ➡️ 서버에서 받은 위치와 클라이언트에서 예측한 위치를 비교
🟢일치하는 경우: 이동 유지(예측이 정확했으므로 추가 보정 없음)
🔴불일치하는 경우: 서버 데이터로 위치를 보정(서버 우선)
이 방식은 클라이언트 예측(Prediction) + 서버 보정(Reconciliation)을 활용하여 네트워크 지연을 줄이면서도 동기화를 유지하는 방식이다.
다만 즉시 보정을 적용하면 캐릭터가 순간이동 하는 문제, 네트워크 지연이 심해 예측과 보정이 반복적으로 일어나면 캐릭터가 떨리는 현상 등의 문제가 발생할 수 있어, 클라이언트에 보정을 적절하게 적용시킬 수 있도록 부드럽게 보간하는 등 점진적으로 조정해야 한다.
🔎클라이언트 보간(예측)
네트워크는 생각보다 강하게 결합되어 있지 않으며, 불안정한 전기 신호이다.
따라서 1/20초 마다 브로드캐스팅 되는 데이터가 클라이언트에서 1/20초 마다 도달한다면, 사용자 경험(UX)에 좋지 않은 영향을 주기 때문에 클라이언트에서는 보간을 한다.(Unreal은 일부 자동 보간)
1️⃣서버 데이터 수신
- 서버는 일정 간격(예: 50ms)마다 캐릭터의 위치를 클라이언트에 전송
- 예: t = 0초에 (0, 0), t = 0.05초에 (5,0)
2️⃣클라이언트 버퍼링
- 클라이언트는 수신된 위치 값을 바로 렌더링하지 않고, 약간의 지연(예: 100ms)을 두고 버퍼에 저장
- 이는 네트워크 지터(Jitter, 패킷 도착 시간 변동)를 보정하고, 보간에 사용할 데이터를 확보하기 위함
3️⃣ 보간 계산
- 클라이언트는 두 위치 값 사이를 시간 비율에 따라 게산
- 예: t = 0.025초일 때, (0, 0)rhk (5, 0) 사이를 보간하면 중간 위치 (2.5, 0)
4️⃣ 렌더링
- 매 프레임(예: 60FPS, 약 16.6ms 간격)마다 보간된 위치를 화면에 반영해 부드러운 이동 구현
🔎AP설계를 기반으로 한 Async(비동기화)
네트워크에서 세션을 유지하기 어려운 모바일 환경 등에서 사용하는 방법으로, "보장된 데이터를 사용" 하여 게임환경을 구축하는 경우이다.
대표적으로 "클래시 오브 클랜"과 같은 게임들이 AP설계에 기반한다.
- 느리지만, 손실 허용이 안되는 TCP 프로토콜을 사용
- 이벤트만 서버로 전송하고, 서버는 이벤트를 검증하여 그 결과를 DB에 저장
- 게임 플레이어 외에는 다른 플레이어의 접속 여부와 관계없이 게임 진행 가능➡️ 이론적으로 확장이 무한
📌 채팅 서버와 온라인 게임 서버의 유사점과 차이점
위에 서술한 모든 과정은 이미 1978년 MUD(Multi User Dungeon)이라는 멀티플레이 게임에서 구현되었다.
현재에는 단지 몇 가지 보간 기법과 예측 기법들이 추가된 것이다.
채팅 서버와 온라인 게임 서버의 유사점과 차이점에 대해 알아보자.
🟢 유사점
- 사용자의 입력을 전체 사용자에게 브로드캐스팅한다.
- 사용자의 세선을 관리한다.
- 채널(서버) 별로 다른 상태를 가진다.
- 채널을 선택하거나, 내 캐릭터를 커스텀 하거나, 친구 목록을 보는 등의 로비가 있다.
🔴 차이점
- 채팅은 데이터 크기가 작으므로 접속이 끊어지고 새로 접속하면, 채널의 모든 정보를 다시 줄 수 있다.
- 채팅은 낮은 Latency를 고려하지 않지만, 게임 서버는 경우에 따라 클라이언트 예측과 서버 보정을 한다.
- 데이터 정확도 면에서, 채팅은 데이터가 유실되면 재전송 필요(TCP)하고 게임 서버는 복구 보다는 최신 데이터 유지(UDP)가 필요하다.
📌 네트워크 구성 진화
네트워크가 실제로 게임 서버에 어떻게 반영되는지, 가상의 회사에서 처음 게임이 출시 되고 게임이 성공적으로 잘 운영됨에 따라 시스템이 어떻게 진화되는지, 어떻게 확장되는지의 과정을 가상의 시나리오로 정리해보려한다.
물론 실제론 이보다도 더 복잡하고 규모가 훨씬 크지만 과정을 이해하는데 초점을 맞춘다.
현재 작은 규모의 경우라고 가정하고 서버 1대, DB 1대로 시작한다.
네트워크 시스템에서의 가장 큰 적은 병목(Bottleneck) 현상이다.
병목 현상이란 다른 서버는 노는데 어느 한 서버는 과부하가 걸려서 전체 시스템의 성능이 떨어지는 현상을 말한다.
이 때문에 DB서버를 분리하였지만, 사용자의 로그인이 많은 시스템의 경우 로그인 서버만 따로 분리하기도 한다.
로그인 서버에서 생성한 인증, 사용자 정보 등의 세션을 가지고 게임 서버로 접속하는 방식을 사용했다.
사용자가 점차 많아지게 되면서 채팅량도 동시에 많아지게 되었다.
이로 인해 게임 서버에서 채팅 서버를 분리하게 되었다.
게임의 업데이트가 빈번해지자 게임 서버에서 별도의 패치 서버(CDN)를 분리하였다.
하지만 복잡해면서 예를 들어 로그인 서버가 터졌다고 가정하면 전체 시스템에 문제가 생기게 되며 크래쉬가 발생하고 운영자체가 불가능해진다.
이후로 서버의 증설이 필요하다는 것을 알게 되고, 병렬로 확장하였다. 이를 클러스터링(Clustering)이라고 한다.
🔎클러스터링: 여러개의 서버(노드)를 하나의 논리적 단위(클러스터)로 묶어 동작하는 방식
1. 클러스터 내부의 서버들은 서로 협력하여 하나의 서비스처럼 동작한다.
2. 특정 서버가 다운되어도 서비스가 계속 유지된다.
3. 로드밸런서를 통해 부하를 균등하게 분산할 수 있다.
서버와 서버의 동기화는 대단히 많은 동기화 시간을 필요로 하기 때문에 게임 서버를 월드(북미 서버, 아시아 서버 등) 단위로 확장하면서, 노는 서버에게 트래픽을 더 몰아주거나(로드 벨런싱) 서버 장애가 발생하였을 때 전체 시스템 마비를 막기 위한 장비로 L4/L7 스위치를 사용했다.
이로 인해 네트워크 구성이 단순해지기 시작했고 관리가 편리해졌다.
게임 유저 수가 많다보니 해킹 공격이 시도되어, 방화벽을 설치하여 적극적으로 차단하기로 하였다.
또 한가지 문제가 생겼는데 접속하는 서버들이 늘어났는데 DB가 한개였다.
그래서 DB도 DB클러스터(NoSQL과 같은 분산 DB 또는 Active-Active 모드의 Replication DB)를 적용하기로 했다.
하지만 자주 변경이 안되는 데이터도 DB에 Access하는 상황이 생겼다.
분산 DB를 구성하게 되면서 저장소(Disk)를 공유하거나, DB 서버간 데이터를 항상 동기화 해야하는 문제가 생긴 것이다.
DB에서 잦은 사용이 되는 것은 메모리 캐쉬 서버(Redis, MemCached)로 분리하고 영구적으로 저장해야 되는 중요한 데이터는 DB에 분리시켜 부하를 줄여주었다.
그럼에도 불구하고 로그인 서버에도 과부하가 걸리는 문제가 발생하였다.
그래서 로그인 서버 앞에 Cache서버를 두고 변동이 거의 없는 데이터들을 대신 받아서 응답하게 하여, 뒤쪽에 있는 서버들의 부하를 줄였다. 일종의 방패 같은 역할인 셈.
이번에는 게임서버와 채팅서버 등 서버간의 통신에서 데이터가 소실되는 경우가 생겼다.
한쪽 서버에 과부하가 걸려서 통신이 원할하지 않는 경우 TCP에서 재전송을 하는데 무한정 연결 세션을 유지하면서 재전송을 할 순 없다.
이러한 상황을 위해 Message Queue(RabbitMQ) 서버를 추가하여 서버간의 통신을 Message Queue에 위임하고, 서버가 과부하 상태일 때 메세지를 일괄 처리하는 방식으로 개선하였다.
이 방식은 비동기 메시징 시스템을 통해 서버의 부하를 줄이고 안정성을 높이는 효과를 가져온다.
다만 단점은 메세지가 큐에 쌓이는 동안 지연(Latency) 발생 가능성이 있다.
🔔 마무리
네트워크 구성이 진화하는 과정에 대해 살펴보았는데, 실제 실무의 게임서버에는 매치메이킹, 결제 서버, 개발 서버, 테스트 서버 등 수 많은 부가 기능이 있기에 더욱 복잡하고 규모가 크다.
온라인 회사가 잘 되면 잘 될수록 시스템은 끊임 없이 늘어난다.
'내배캠 > Unreal Engine' 카테고리의 다른 글
채팅으로 하는 숫자 야구 게임 구현(Listen Server) (0) | 2025.03.19 |
---|---|
언리얼 네트워크와 객체 통신 (0) | 2025.03.12 |
네트워크 개념 (0) | 2025.03.10 |
동적 멀티캐스트 델리게이트 (Dynamic Multicast Delegate) (0) | 2025.02.11 |
Particle과 Sound 효과 연출 (0) | 2025.02.07 |