보스가 뜨면 왜 렉이 걸릴까?
MMO에서 보스가 등장하면 왜 렉이 걸리는지 설명하는 영상이다. 한곳에 모인 인원이 N명이면 서버가 보내야 할 상태 갱신은 N × (N − 1)로 늘고, 시야 반경을 넓히면 보이는 인원이 반경의 제곱으로 늘어 부담이 더 커진다. 게임은 보내는 양을 줄이거나 한곳에 모이는 인원을 나누는 방식으로 대응한다.
01사람이 몰린다
보스가 뜨는 순간, 흩어져 있던 플레이어가 한곳으로 · ▶ 이 장면 보기
화면의 점 200개가 플레이어다. 평소에는 맵 전체에 흩어져 있어서 서로 보이지 않고, 서버가 서로에게 전해 줄 것도 적다.
보스가 등장하면 플레이어가 보스 주변 타원 안으로 모여든다. 왼쪽 아래의 보스 주변 인원 숫자가 이동에 따라 올라가 최대 200명에 이른다. 같은 존, 같은 시야 안에 수십에서 수백 명이 들어오는 상황이 이후 모든 문제의 출발점이다.
02브로드캐스트는 N × (N − 1)
한 명의 변화를 보는 사람 모두에게 복제해서 보낸다 · ▶ 이 장면 보기
한 명이 움직이면 서버는 그 변화를 그 사람을 보고 있는 나머지 N − 1명에게 각각 복제해서 보낸다. N명 모두 움직이면 한 틱에 보내야 할 갱신은 N × (N − 1)이다. 왼쪽 그림에서 연결선이 인원 증가에 따라 빠르게 빽빽해진다.
오른쪽 표는 이동만 계산한 틱당 브로드캐스트 수다.
N = 10: 90N = 50: 2,450N = 100: 9,900N = 200: 39,800
200명이면 틱당 39,800 갱신이고, 20Hz로 곱하면 초당 796,000 갱신이다. 갱신당 50바이트로 잡으면 약 40MB/s, 약 320Mbps가 존 서버 하나에서 나간다. 갱신은 보통 클라이언트마다 틱당 패킷 하나로 묶어 보내므로 패킷 수는 N × 20 = 4,000개 수준이고, 인원의 제곱으로 느는 것은 바이트다.
이동뿐 아니라 공격, 이펙트, 버프 등 상태 하나가 바뀔 때마다 보는 사람 수만큼 복제된다. 그래서 비용은 인원의 제곱으로 늘고, 200명은 20명보다 갱신이 10배가 아니라 약 100배 많다.
03시야가 넓으면 더 나빠진다
반경이 2배면 보이는 사람은 약 4배 · ▶ 이 장면 보기
왼쪽은 시야 반경 r, 오른쪽은 반경 2r이다. 같은 필드에서 원 안에 들어온 점의 수가 각 패널 오른쪽 위에 보이는 인원으로 표시된다.
- 반경이 2배면 면적은 4배이고, 보이는 인원은 밀도가 고르면 약 4배가 된다. 브로드캐스트 양은 N × 보이는 인원이므로 이것도 약 4배가 된다.
- 주변에 누가 있는지 찾는 AOI 검색 비용도 r²에 비례한다. 확인해야 할 그리드 칸이 4배로 늘어난다.
- 클라이언트도 4배를 받고 4배를 그린다. 다운링크, CPU, GPU 부담이 모두 늘어 클라이언트 FPS가 떨어진다.
- 모두가 한 시야 안에 몰리면 결국 N × (N − 1)이 된다. 보스 앞에서는 반경이 넓을수록 이 최악의 경우에 빨리 도달한다.
04보스 전투가 더하는 것
광역기 · 이펙트 · AI · HP 갱신도 모두 인원과 함께 곱으로 커진다 · ▶ 이 장면 보기
보스 전투는 이동 외에도 인원과 함께 곱으로 커지는 일을 더 만든다.
- 광역기 판정: 한 번의 공격에 N명의 히트 체크와 데미지 계산을 하고, 그 결과를 다시 보는 사람들에게 알린다. 카드 예시에서는 16명 피격 × 보는 사람 200명으로
DamageNoti3,200개가 생긴다. - 이펙트, 버프, 투사체: 버프의 시작, 종료, 중첩과 투사체의 생성, 이동, 소멸이 하나하나 브로드캐스트 대상이다.
- 어그로와 AI 계산: 보스는 N명의 위협 목록을 다시 계산하고 타깃을 고르고 경로를 탐색한다.
- 보스 HP와 페이즈 갱신: HP가 바뀔 때마다 참가자 200명 모두에게 갱신을 보내고, 페이즈 전환은 대량 이벤트를 한꺼번에 만든다.
05어디서 터지나
서버 CPU · 틱 · 아웃바운드 · 클라 수신 · 렌더가 함께 오른다 · ▶ 이 장면 보기
보스 주변 인원이 20명에서 200명으로 늘어나는 동안 다섯 개 지표가 함께 움직인다. 다섯 가지는 모두 인원 N에서 각각 나오는 결과다.
- 존 로직 스레드 CPU: 틱이 50ms 예산을 넘는 순간 100%에 닿는다. 존 로직이 한 스레드에서 돌기 때문에 한 코어만 100%가 되고, 코어를 늘려도 해결되지 않는다.
- 틱 처리시간: 200명에서 약 113ms로 예산 50ms를 넘는다. 존 전체가 서버렉에 걸린다.
- 아웃바운드: 20Hz를 유지한다고 하면 약 318Mbps까지 오른다. 실제로는 틱이 113ms면 약 9Hz로 떨어진다. pps와 대역폭이 급등하고 송신 큐가 쌓인다.
- 클라이언트 다운링크: 아웃바운드와 같은 기준(이동만, 20Hz)으로 약 200KB/s까지 오른다. 느린 회선부터 밀리고 끊긴다.
- 클라이언트 FPS: 60에서 16까지 떨어진다. 수백 캐릭터와 이펙트를 그리느라 클라렉이 생긴다.
인프라 쪽에서는 보스 시간대에 특정 존 서버만 아웃바운드 pps와 대역폭이 급등하고, 한 코어가 100%가 되고, 연결 끊김이 늘어나는 형태로 보인다. 위 수치는 인원에 따라 늘어나는 모양을 보여주기 위한 계산값이다.
06게임은 이렇게 줄인다
보내는 양을 줄이거나, 모이는 인원을 나눈다 · ▶ 이 장면 보기
왼쪽 그림은 거리별 갱신 빈도다. 가까운 대상은 자주, 먼 대상은 드물게 갱신한다. 오른쪽에 게임이 쓰는 대응 방법 여섯 가지가 나온다.
- 거리별 갱신 빈도(LOD): 가까우면 20Hz, 멀면 2~5Hz로 보낸다.
- 시야 인원 상한: 가까운 K명만 상세하게 동기화하고 나머지는 요약 정보만 보낸다.
- 혼잡 시 시야 반경 자동 축소: 인원이 몰린 곳에서만 반경을 줄인다.
- 묶어 보내기와 델타 압축: 클라이언트마다 틱당 패킷 1개로 묶고, 바뀐 값만 보낸다.
- 채널, 인스턴스 분리: 채널·인스턴스 사본으로 인원 자체를 나눈다. 보스 전용 스레드나 서버는 부하가 다른 존에 번지지 않게 격리할 뿐, 그 안의 N은 그대로다.
- 클라이언트 그래픽 LOD와 이펙트 컬링: 멀리 있는 캐릭터와 남의 이펙트는 간략하게 그린다.
정리하면 보스전 렉 대응은 보내는 양(N², r²)을 줄이거나 한곳에 모이는 N을 나누는 것이다.
이 영상에 나온 용어는 용어집에 정리했다.