게임 렉 백서
한국어

게임 렉
백서

화면이 뚝뚝 끊기거나 캐릭터가 순간이동하거나 접속이 끊기는 원인을 내 게임 화면부터 서버의 데이터베이스까지 13개 층으로 나눠 설명합니다. 원인마다 확인 방법과 담당 팀을 적었고 실험에서 조건을 바꿔 보며 확인할 수 있습니다. MMO 사례를 중심으로 썼지만 대부분은 장르와 상관없이 온라인 게임 전반에 해당합니다.

00시작하기

렉을 만드는 네 가지 요인

원인은 백 가지가 넘지만 렉을 만드는 요인은 네 가지로 묶입니다. 패킷이 늦게 오거나, 들쭉날쭉 오거나, 아예 안 오거나, 누군가 계산을 멈추는 경우입니다. 게임은 이 요인들을 가리려고 여러 기술을 쓰는데 가리다 실패한 흔적이 우리가 보는 렉의 “모양”입니다.

MMO에서 내 화면에 보이는 세계는 서버가 보내 준 패킷으로 다시 그린 화면입니다. 서버는 게임마다 다르지만 보통 1초에 10~30번 게임 상태를 계산하고(이 한 번을 틱이라고 합니다), 그 결과 중 각 플레이어 주변의 변화만 골라 패킷으로 보냅니다. 내 PC는 도착한 패킷을 읽고 화면을 그립니다. 그래서 렉은 대부분 “패킷이 제때 오지 않은 것”을 게임이 어떻게 보여 주느냐의 문제입니다.

네 가지 밖의 경우도 있습니다. 서버와 내 PC가 같은 일을 서로 다르게 계산하면(이동 규칙 차이, 버그) 회선이 멀쩡해도 고무줄이나 안 보임이 생깁니다. 이런 렉은 핑과 상관없이 같은 장소·같은 행동에서 되풀이되는 것이 단서입니다.

요인에서 증상까지

비유

택배로 생각해 보세요. 배송이 늘 3일 걸리면 지연, 어떤 건 하루 어떤 건 닷새 걸리면 지터, 상자가 사라지면 손실, 물류센터가 문을 닫으면 정체입니다. 게임은 “상자가 늦거나 안 오면 앞뒤 상자로 짐작해 채우기(보간·외삽)”, “안 오면 다시 보내 달라고 하기(재전송)” 같은 방법으로 버팁니다.

시간 감각부터 맞추기

렉 이야기는 대부분 밀리초(ms, 1/1000초) 단위입니다. 아래 표의 숫자 몇 개만 기억해도 게임개발팀·인프라팀의 말이 훨씬 잘 들립니다.

기준시간의미

모든 층에 공통인 대기열의 성질

CPU, 디스크, 데이터베이스, 공유기, 통신사 회선. 층은 달라도 구조는 같습니다. 요청을 처리하는 워커(CPU 코어, 스레드, DB 커넥션 등)가 있고 그 앞에 대기열이 생깁니다. 워커가 한가하면 대기열이 비어 있지만 바쁜 정도(이용률)가 80~90%를 넘어서면 대기열이 급격히 길어집니다. 워커 하나에 요청이 무작위로 올 때, 평균 대기는 이용률 50%에서 처리 시간만큼, 80%에서 4배, 90%에서 9배가 됩니다. “CPU가 아직 10% 남았는데 왜 렉이죠?”의 답이 여기 있습니다. 게다가 모니터링 화면의 CPU 수치는 보통 여러 코어와 1~5분을 평균한 값이라, 코어 하나만 100%인 상황이나 몇 초 동안만 몰린 순간을 가립니다.

이 백서가 다루는 것과 다루지 않는 것

게임 화면을 그리는 내 PC·폰부터 집 네트워크, 통신사, 데이터센터, 서버와 데이터베이스까지, 온라인 게임의 플레이 중 렉을 만드는 원인을 다룹니다. 게임 화면을 영상으로 받아 보는 클라우드 게이밍, 별도 서비스로 도는 음성 채팅, 패치·다운로드 속도는 구조가 달라 다루지 않습니다. 다만 그 안의 네트워크 원인(와이파이, 버퍼블로트, 회선 혼잡 등)은 여기 있는 원인과 같습니다.

01전체 지도

패킷의 이동 경로: 입력에서 서버 DB까지

스킬 버튼을 누르면 그 신호는 내 PC와 집, 통신사, 데이터센터를 지나 서버에 닿습니다. 서버 안의 여러 층에서 처리된 결과는 같은 층들을 거꾸로 지나 화면에 그려집니다. 모두 13개 층이고 어느 층이든 막히면 렉입니다. 아래 지도에서 층을 누르면 해당 장으로 이동합니다.

02직접 해보기

렉 실험실

서버 한 대, 회선 하나, 내 PC 하나로 이루어진 작은 시뮬레이션입니다. 조건을 하나씩 바꾸며 뚝뚝 끊김, 순간이동, 고무줄, 몰아치기, 슬로우모션, 입력 지연, 멈춤, 접속 끊김이 각각 어떻게 만들어지는지 보세요. 패킷 타임라인은 패킷이 언제 보내지고 언제 도착했는지를 선으로 보여 줍니다. 선이 기울수록 오래 걸린 것이고 ×는 사라진 패킷입니다.

03보이는 모양으로 찾기

증상 사전

플레이어는 “렉 걸려요”라고만 말하지만 렉의 모양은 원인을 꽤 많이 알려 줍니다. 각 증상의 작은 그림은 화면 속 캐릭터가 지나간 자리입니다. 점이 겹치면 멈춘 것, 벌어지면 빨라지거나 건너뛴 것입니다.

뚝뚝 끊김

움직임이 매끄럽지 않고 짧게 멈췄다 움직이기를 반복합니다. 핑 수치가 멀쩡하면 내 PC 프레임(클라이언트·OS) 문제, 핑이 들쭉날쭉하면 와이파이·회선의 지터일 가능성이 큽니다. 다만 게임 안 핑 표시는 대개 프레임마다 도는 게임 루프 안에서 재기 때문에, 프레임이 튀면 핑 숫자도 함께 튈 수 있습니다.

순간이동

캐릭터가 이동 과정 없이 멀리 떨어진 위치로 한 번에 옮겨집니다. 대개 패킷이 한동안 끊겼습니다. 손실, 짧은 회선 끊김, 서버 멈춤, 외삽 실패를 봅니다. 다른 사람은 멀쩡한데 한 사람만 튀면 그 사람의 회선을 먼저 의심합니다.

고무줄

내 캐릭터가 앞으로 가다가 방금 지나온 자리로 끌려 돌아갑니다. 내 화면(예측)과 서버 판정이 어긋났습니다. 내 입력이 서버에 못 갔거나(손실), 서버의 이동 검증이 잘랐거나, 이동 계산이 서로 다릅니다.

몰아치기

멈춰 있던 화면이 다시 움직이면서 밀린 움직임·타격·데미지가 한꺼번에 빠르게 지나갑니다. 어딘가에서 패킷이 쌓여 있다가 한 번에 풀렸습니다. TCP 재전송 대기, 서버 따라잡기, 클라 처리 밀림이 대표적입니다.

슬로우모션

모든 것이 느리게 움직입니다. 스킬 시전과 몬스터 이동이 늘어진 것처럼 보입니다. 서버 설계에 따라서는 속도는 그대로인 채 뚝뚝 끊김·순간이동으로 나타나기도 합니다. 서버가 틱을 제시간에 끝내지 못합니다. 회선은 멀쩡하니 게임 밖에서 잰 핑은 그대로이고 게임 안 핑은 서버 처리 대기가 섞여 있으면 조금 오를 수 있습니다. 인원 폭증, 시야 계산, 브로드캐스트, 메모리 부족을 봅니다.

입력 지연

누르고 나서 결과가 나타나기까지 시간이 걸립니다. 화면 자체는 매끄러울 수 있습니다. 왕복 시간(핑)이 길거나, 어딘가에 대기열이 쌓여 있습니다. 거리, 공유기 대기열, Nagle(작은 패킷을 모았다 보내는 TCP 기능), 서버 대기열을 봅니다. 핑이 낮은데도 늘 굼뜨면 V-Sync·낮은 FPS 같은 내 PC 쪽이나, 행동마다 서버 확인을 기다리는 설계(동기화 방식 장)를 봅니다.

멈춤

화면 속 모든 것이 잠깐(0.5초~수 초) 멈췄다가 다시 움직입니다. 서버가 통째로 멈췄거나(GC, 데드락, 동기 호출), 회선이 잠깐 끊겼거나, 내 PC가 멈췄습니다.

씹힘·롤백

분명히 한 행동이 없던 일이 되거나, 결과가 한참 뒤 뒤집힙니다. 요청이 사라졌거나(손실, 대기열 넘침), 서버가 내 화면과 다르게 판정했거나(판정 시점 차이, 선연출 뒤 거절), 저장 도중 실패했습니다(DB 잠금·장애, 서버 크래시).

접속 끊김

게임 중에 연결이 끊어져 로그인 화면이나 재접속 창으로 돌아갑니다. 타임아웃 시간 안에 패킷이 하나도 오지 않았습니다. 긴 회선 끊김, 유휴 타임아웃, 서버 크래시·재시작, 타임아웃보다 오래 멈춘 서버나 내 PC(긴 로딩)를 봅니다. 안내 없이 게임 자체가 꺼졌다면 연결보다 클라이언트 강제 종료(크래시, 메모리 부족)를 먼저 봅니다.

접속 불가·무한 로딩

게임 안으로 들어가지 못하거나, 로딩·입장 화면에서 멈춰 있습니다. 새 연결을 받아 주는 곳(서버의 접속 대기열, 방화벽, 로그인 서버, DB)이 가득 찼습니다. 점검 직후에 특히 많습니다.

안 보임·유령 개체

있어야 할 NPC·몬스터·플레이어가 내 화면에만 없거나, 이미 사라진 개체가 내 화면에만 남아 있습니다. 속도 문제보다는 패킷 하나가 빠졌거나 그리기에 실패한 상태입니다. 채널·페이즈 차이, 등장·퇴장 알림 유실, 로딩 중 폐기, 에셋 로딩 실패를 봅니다. 시야를 벗어났다 돌아오면 보이는지가 가장 분명한 단서입니다.

04동기화 설계

동기화 방식과 체감

어떤 게임은 핑 150ms에서도 아무렇지 않고 어떤 게임은 60ms에서도 굼뜹니다. 같은 회선이라면 이 차이는 대개 클라이언트와 서버가 “무엇을, 언제, 누가 결정하느냐”를 정해 둔 방식인 동기화 설계에서 나옵니다. 핑에 민감한 설계 가운데 일부는 의도된 선택이고 일부는 잘못 만든 결과입니다.

네트워크 게임은 모두 같은 문제를 풉니다. 서버와 내 PC 사이에는 반드시 시간 차이가 있고 둘 중 누군가는 “아직 확정되지 않은 것”을 어떻게 다룰지 정해야 합니다. 선택지는 네 가지입니다.

  • 기다린다: 서버가 확정할 때까지 아무것도 보여 주지 않습니다. 정확하지만 핑이 곧 반응 속도가 됩니다.
  • 먼저 보여 주고 나중에 고친다: 내 행동은 즉시 연출하고 서버 결과가 다르면 바로잡습니다. 빠르지만 가끔 고무줄·취소가 보입니다.
  • 미리 예약해 둔다: “1.5초 뒤 내려찍기”처럼 미래 시각과 함께 알려 줍니다. 연출 시간이 핑보다 길면 핑이 아예 안 보입니다.
  • 모두가 같은 계산을 한다: 입력만 주고받고 각자 똑같이 계산합니다(락스텝, 롤백). 전송량은 작지만 한 명의 지연이 모두에게 번집니다.

핑 민감도는 장르보다 두 가지 질문이 크게 좌우합니다. 첫째는 핵심 행동 하나가 서버 왕복을 몇 번 기다리는가이고 둘째는 게임 규칙이 허용하는 시간이 “핑 + 사람의 반응 시간”보다 넉넉한가입니다.

흔히 쓰는 동기화 방식

방식어떻게 동작하나흔한 곳핑 150ms에서 보이는 모습약한 곳
요청-응답
서버 확인 후 표시
누르면 서버에 묻고 답이 오면 그때 연출한다.턴제·카드·방치형, 상점·거래·제작 UI, 오래된 MMO의 스킬·아이템 사용모든 행동이 0.2초쯤 늦게 시작. 턴제라면 거의 못 느낌연속 행동, 한 화면에 왕복이 여러 번 있는 UI
상태 동기화 + 보간
서버 권위
서버가 게임 상태를 틱마다 보내고 클라는 두 상태 사이를 이어 그린다.대부분의 MMO에서 다른 플레이어·몬스터 표시다른 사람은 약 0.2초 과거 모습. 평소엔 티가 거의 안 남지터(도착 간격의 흔들림)·손실 → 순간이동, 느린 틱레이트
클라 예측 + 서버 보정내 입력은 즉시 반영하고 서버 결과가 오면 비교해 바로잡는다.FPS, 액션 MMO, 대부분의 MMO 이동내 조작은 즉시. 가끔 짧은 고무줄서버와 계산이 다르면 잦은 보정
지연 보상
서버 되감기 판정
서버가 공격자가 보던 과거 시점으로 되감아 명중을 판정한다.FPS, 논타겟 액션쏜 사람은 공정하게 느끼지만 맞는 사람은 “엄폐했는데 맞음”맞는 쪽의 억울함. 공격자 핑이 높을수록 크게 되감아 심해짐
명령·목적지 동기화“여기로 가라”, “이 대상 공격”처럼 의도만 보내고 양쪽이 알아서 계산한다.클릭 이동 MMO, 탭 타겟 전투, MOBA 일부출발이 살짝 늦을 뿐 이동과 공격은 매끄러움경로·결과가 어긋나면 보정 필요
이벤트 예약
서버 시각 기반
“서버 시각 T에 시작”처럼 미래 시각과 함께 알려 주고 각자 그 시각에 재생한다.레이드 보스 패턴, 컷신, 정각 이벤트예고가 핑보다 길면 사실상 영향 없음예약보다 늦게 도착하면 앞부분을 건너뜀
결정론적 락스텝모두의 입력을 모아 같은 턴에 똑같이 계산한다. 입력에는 고정 지연을 붙인다.RTS(스타크래프트 계열), 일부 협동·퍼즐 게임모든 입력이 일정하게 늦음(누르는 즉시 효과음·표시로 가림). 지터가 크면 모두가 멈춤지터·손실, 가장 느린 한 명
롤백
예측 후 되감기
상대 입력을 예측해 먼저 진행하고 틀리면 과거로 되감아 다시 계산한다.격투 게임(GGPO 계열), 일부 액션·스포츠조작감은 거의 즉시(보통 1~3프레임 입력 지연). 상대 동작이 가끔 몇 프레임 튐핑이 크면 되감기 폭이 커져 순간이동처럼 보임
클라이언트 권위각자 자기 결과를 결정하고 서버는 전달·기록만 한다.일부 모바일·캐주얼, P2P·릴레이 구조내 화면은 쾌적. 다른 사람 화면과 결과가 어긋남해킹, “나는 맞혔는데 안 맞았다”

실제 게임은 이 방식들을 섞어 씁니다. 이동은 예측, 스킬은 선연출 후 확정, 보스 패턴은 이벤트 예약, 거래는 요청-응답처럼 행동마다 다르게 고르는 것이 보통입니다.

핑 150ms에서도 쾌적한 게임의 공통점

1. 행동 하나에 왕복이 한 번도 끼지 않습니다. 버튼을 누르면 애니메이션·효과음·이펙트를 즉시 시작하고(선연출), 서버 결과는 데미지 숫자처럼 늦어도 티 안 나는 부분에만 씁니다.

2. 게임 규칙이 허용하는 시간이 핑보다 넉넉히 깁니다. 보스 예고가 1~2초면 패킷이 0.2초쯤 늦게 오고 사람 반응에 0.25초를 써도 충분히 피할 수 있습니다. 내 스킬도 시전 시간이 있으면, 시전 바가 차는 동안 서버 확인이 함께 끝나서 기다림이 시전 시간 안에 숨습니다. 탭 타겟 MMO가 핑에 둔감한 가장 큰 이유입니다. 반대로 0.5초 안팎의 짧은 예고는 핑 150ms만 돼도 보고 피하기 어렵습니다(아래 판정 구간 실험).

3. 연속 행동을 미리 받아 둡니다. 다음 스킬을 쿨다운이 끝나기 전에 눌러도 받아 두는 선입력(스킬 큐)이 있으면, 연계 사이에 왕복 시간이 끼지 않습니다.

4. 지터를 흡수합니다. 보간 버퍼와 서버 시각 기반 연출은 “대개 150ms, 가끔 250ms” 걸려 오는 패킷을 늘 250ms쯤 늦은 일정한 흐름으로 바꿉니다. 조금 더 과거를 보는 대신 매끄럽습니다. 사람은 일정한 늦음에는 금방 익숙해지지만 들쭉날쭉함에는 익숙해지기 어렵습니다. 잘 만든 게임은 지터가 커지고 작아지는 데 맞춰 버퍼 길이를 스스로 늘리고 줄입니다.

5. 판정이 “내가 본 것”과 맞습니다. 회피·명중을 플레이어가 본 시점 기준으로 판정하거나(지연 보상), 애초에 위치가 중요하지 않은 규칙(대상 지정)을 씁니다.

6. 한 명의 지연이 다른 사람을 기다리게 하지 않습니다. 서버 권위 구조에서는 내 핑이 나빠도 다른 사람은 멀쩡합니다. 락스텝이나 호스트 구조에서는 가장 느린 한 명이 모두의 체감을 정합니다.

의도한 설계와 잘못 만든 설계 구분하기

핑에 민감한 이유는 의도한 설계일 때도 있고 잘못 만든 탓일 때도 있습니다.

의도된 선택일 수 있는 것
  • 짧은 판정 구간: 패링 0.2초, 저스트 회피처럼 짧은 판정 구간 자체가 재미인 게임입니다. 핑만큼 반응할 시간이 줄고 지터가 타이밍을 흐트러뜨리는 건 피할 수 없어서 지연 보상이나 지역 서버로 줄입니다.
  • 치팅을 막는 서버 확정: 재화·아이템·순위처럼 절대 속으면 안 되는 결과는 서버 확인을 기다리는 게 맞습니다.
  • 락스텝: 수백 개 유닛을 입력만으로 동기화하려면 가장 현실적인 구조입니다. 대신 입력 지연을 핑에 맞춰 조절합니다.
  • 공정성: 지연 보상을 일부러 약하게 해서 핑 높은 사람 때문에 맞는 쪽이 억울해지지 않게 하는 선택도 있습니다.
잘못 만들었을 가능성이 큰 신호
  • 키보드·패드로 직접 움직이는 게임인데 이동·기본 공격까지 서버 확인을 기다림: 예측 없이 만들면 핑이 그대로 손맛이 됩니다. 클릭 이동처럼 명령을 내리는 조작은 서버 확인을 기다려도 덜 드러나서, MOBA 등에서는 일부러 고르기도 합니다.
  • UI 한 번에 왕복이 여러 번: 창 열기 → 목록 받기 → 확인 → 구매가 각각 왕복이면 150ms 핑에서 0.7~0.8초가 걸립니다. 한 번에 묶을 수 있습니다.
  • 회선 핑은 낮은데 일정하게 굼뜸: Nagle(작은 패킷을 모았다 보내는 TCP 기본 동작, TCP_NODELAY로 끔), 요청을 다음 틱까지 모았다가 결과도 다음 틱에 보내는 이중 대기, 행동마다 DB 저장이 끝나야 응답하는 구조를 의심합니다. 내 PC의 V-Sync·낮은 FPS도 같은 느낌을 줍니다.
  • 스킬 큐 없이 “확인 후 다음 입력”: 연계마다 왕복 시간이 끼어 핑만큼 DPS가 줄어듭니다.
  • 도착 즉시 재생: 보간 버퍼나 서버 시각 없이 받은 순서대로 연출하면, 지터가 그대로 애니메이션의 뚝뚝 끊김이 됩니다.

동기화 설계에서 렉을 만드는 원인

서버 응답 후에만 연출 (요청-응답 방식) Request-response (no client-side feedback)

버튼을 누르면 서버 답이 올 때까지 애니메이션도 소리도 없습니다. 핑이 곧 반응 속도가 됩니다.

왜: 스킬·이동·줍기를 서버 확인이 온 뒤에 재생 → 그러면: 누른 순간부터 왕복 시간 + 틱 대기만큼 아무 반응 없음 → 화면에서는: 핑 150ms면 모든 행동이 0.2초씩 굼뜸

증상: 입력 지연 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

순차 왕복이 많은 프로토콜 (chatty) Chatty protocol / sequential round trips

조작 한 번에 서버 왕복이 여러 번 순서대로 필요하면, 핑이 그 횟수만큼 곱해집니다.

왜: 상점 열기 → 목록 요청 → 가격 확인 → 구매 → 인벤토리 갱신을 각각 따로 요청 → 그러면: 앞 요청의 답을 받아야 다음 요청을 보냄 → 화면에서는: 핑 150ms에서 한 번 사는 데 1초 가까이. 로딩이 유난히 김

증상: 입력 지연, 접속 불가·무한 로딩 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

스킬 선입력 없음 No input/spell queue

앞 스킬이 서버에서 끝났다는 확인을 받아야 다음 스킬을 누를 수 있으면, 연계마다 왕복 시간이 끼어듭니다.

왜: 다음 스킬 입력을 “이전 스킬 확정 후”에만 받음 → 그러면: 스킬 사이마다 핑만큼 빈 시간이 생김 → 화면에서는: 연계 사이마다 빈틈이 생기고 핑이 높을수록 DPS가 줄어듦

증상: 입력 지연, 씹힘·롤백 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

핑에 먹히는 짧은 판정 구간 Timing window too short for latency + reaction

회피·패링·가드처럼 반응해야 하는 시간이 짧으면, 핑이 그 시간을 먹어 버려 피할 수 없는 공격이 생깁니다.

왜: 보스 공격 예고 0.5초, 패링 판정 0.2초처럼 짧은 판정 구간 → 그러면: 예고를 늦게 보고(내려오는 지연 + 보간), 내 입력도 늦게 도착(올라가는 지연 + 틱 대기) → 화면에서는: 분명 피했는데 맞음, 패링이 씹힘

증상: 씹힘·롤백, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발, 인프라팀·서버 인프라

지연 보상 없는 판정 Server-now hit validation

서버가 “지금 서버에 있는 위치”로만 명중을 판정하면, 내가 본 화면과 판정이 어긋납니다.

왜: 내 화면의 상대는 약 0.2초 과거 위치(핑 150ms, 보간 100ms일 때) → 그러면: 서버는 현재 위치로 판정해 내가 조준한 곳엔 이미 없음 → 화면에서는: 분명 맞혔는데 빗나감. 움직이는 대상을 앞질러 쏴야 함

증상: 씹힘·롤백 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

지연 보상 과다 Excessive lag compensation

공격자 기준으로 너무 멀리 되감아 주면, 맞는 쪽은 이미 숨었는데도 맞습니다.

왜: 핑 높은 공격자를 위해 서버가 크게 되감아 판정 → 그러면: 맞는 사람 화면에서는 이미 엄폐한 뒤 → 화면에서는: “벽 뒤에서 맞았다”, 핑 높은 사람이 유리

증상: 씹힘·롤백 · 주 담당 게임개발팀·서버 개발

클라이언트 권위 Client-authoritative results

각자 자기 결과를 결정하면 내 화면은 쾌적하지만 다른 사람 화면과 결과가 어긋나고 해킹에 약합니다.

왜: 위치·명중을 클라이언트가 정하고 서버는 전달만 → 그러면: 두 사람이 서로 먼저 맞혔다고 주장, 서버는 검증 못 함 → 화면에서는: 상대가 순간이동·벽 통과, “나는 맞혔는데 안 맞음”

증상: 순간이동, 씹힘·롤백 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

락스텝에서 가장 느린 플레이어 대기 Lockstep waits for the slowest peer

모두가 같은 턴을 함께 계산하는 구조에서는, 한 명의 입력이 늦으면 모두가 기다립니다.

왜: 턴마다 모든 플레이어의 입력이 모여야 계산 가능 → 그러면: 한 명의 입력이 지터·손실로 늦게 도착 → 화면에서는: 모든 사람이 동시에 멈칫, 심하면 “플레이어 기다리는 중” 창

증상: 멈춤, 뚝뚝 끊김, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

롤백 넷코드의 예측 실패 Rollback misprediction

상대 입력을 예측해 먼저 보여 주다가 틀리면 되감아 다시 계산합니다. 핑이 클수록 되감는 폭이 커집니다.

왜: 상대가 입력을 바꿈(예측과 다름) → 그러면: 실제 입력이 핑의 절반만큼 늦게 도착해 그만큼 되감아 재계산 → 화면에서는: 상대 동작이 몇 프레임 건너뛰거나 갑자기 바뀜

증상: 순간이동 · 주 담당 게임개발팀·클라이언트 개발

타임스탬프 없는 도착 즉시 재생 Events played on arrival (no timestamps)

서버 이벤트에 발생 시각을 붙이지 않고 받자마자 재생하면, 네트워크 지터 때문에 연출 타이밍이 그대로 들쭉날쭉해집니다.

왜: “공격 시작”, “이펙트 재생” 이벤트를 도착 즉시 실행 → 그러면: 패킷마다 도착 시간이 달라 간격이 들쭉날쭉 → 화면에서는: 연속 공격 모션이 빨라졌다 느려졌다, 보스 패턴 타이밍이 매번 다름

증상: 뚝뚝 끊김, 몰아치기 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

이중 틱 대기 Double tick quantization

요청을 다음 틱까지 모았다가 처리하고 결과도 그다음 틱에 보내면 틱 간격이 두 번 더해집니다.

왜: 받은 요청은 다음 틱에서 처리 → 그러면: 처리 결과도 다음 전송 틱에 모아서 보냄 → 화면에서는: 회선 핑은 낮은데 반응이 틱 간격의 1.5배쯤 일정하게 늦음. 10틱 서버면 평균 0.15초, 최악 0.2초

증상: 입력 지연 · 주 담당 게임개발팀·서버 개발

너무 엄격한 서버 검증 Over-strict server validation

이동 속도·쿨타임·사거리를 서버가 너무 엄격하게 검사하면, 지터로 몰려 온 정상 입력까지 거절합니다.

왜: “한 틱에 이동 가능한 거리”, “쿨타임 0ms 허용” 같은 엄격한 기준 → 그러면: 지터로 명령 두 개가 한 틱에 몰려 도착하면 규칙 위반으로 판정 → 화면에서는: 고무줄, 쿨타임 됐는데 스킬 거절

증상: 고무줄, 씹힘·롤백 · 주 담당 게임개발팀·서버 개발

호스트(방장) 구조 Listen server / host advantage

한 플레이어의 PC가 서버 역할을 하면, 그 사람의 회선과 PC 성능이 모두의 체감을 정합니다.

왜: 방장 PC가 서버 역할(P2P, 리슨 서버) → 그러면: 방장 회선이나 PC가 느리면 모두에게 전파, 방장은 핑 0 → 화면에서는: 방장만 유리, 방장이 나가면 모두 멈춤·접속 끊김

증상: 뚝뚝 끊김, 멈춤, 접속 끊김 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발, 인프라팀·서버 인프라

선연출 뒤 서버 거절 Client-side feedback rejected by server

내 화면에서 먼저 보여 준 타격·스킬을 서버가 나중에 인정하지 않으면, 분명히 본 결과가 없던 일이 됩니다.

왜: 타격 이펙트·스킬 모션을 서버 확인 전에 먼저 재생(선연출) → 그러면: 서버가 사거리·대상 위치·쿨다운·자원을 다시 따져 보고 거절 → 화면에서는: 피가 튀었는데 데미지 없음, 스킬 모션만 나가고 효과 없음, 쿨다운만 돎

증상: 씹힘·롤백, 고무줄 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

명령 동기화의 경로 계산 불일치 Command sync with divergent pathing

“여기로 가라”만 주고받고 경로는 양쪽이 각자 계산하면, 계산이 조금만 달라도 캐릭터나 몬스터가 다른 경로로 가다가 제자리로 끌려옵니다.

왜: 클릭 이동·몬스터 추적에서 목적지만 보내고 경로는 클라이언트가 따로 계산 → 그러면: 지형 데이터 차이, 다른 캐릭터와의 충돌, 계산 순서 차이로 서버와 다른 경로로 이동 → 화면에서는: 몬스터가 벽을 뚫고 가다 휙 옮겨짐, 클릭한 캐릭터가 미끄러지듯 방향을 틂

증상: 순간이동, 고무줄 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

낮은 스냅샷 전송률 Low snapshot / update rate

서버가 위치 업데이트(스냅샷)를 1초에 몇 번만 보내면 보간 버퍼를 그만큼 길게 잡아야 해서, 다른 캐릭터를 더 먼 과거로 봅니다.

왜: 전송량을 아끼려고 위치 업데이트를 1초에 5~10번만 보냄 → 그러면: 매끄럽게 그리려면 버퍼를 패킷 간격의 2배(200~400ms)로 잡아야 하고, 짧게 잡으면 패킷 하나만 놓쳐도 멈춤 → 화면에서는: 상대의 방향 전환이 늦게 보이고 판정과 어긋남. 버퍼가 짧으면 뚝뚝 끊기고 손실 때 순간이동

증상: 뚝뚝 끊김, 순간이동, 씹힘·롤백 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

05영향 범위

한 명만 느릴 때, 한쪽만 이상할 때

렉 제보에서 가장 헷갈리는 경우는 몇 사람만, 또는 한쪽만 겪을 때입니다. 느린 한 사람이 다른 사람 눈에 어떻게 보이는지, 그 사람 때문에 다른 사람까지 느려지는지는 서버가 입력을 처리하는 방식과 동기화 방식에 따라 완전히 달라집니다. 같은 PC에서 띄운 두 클라이언트 중 한쪽만 NPC가 안 보이는 현상도 이 장에서 다룹니다.

특정 유저, 특정 회선만 느리면

요즘 MMO 대부분은 서버 권위 구조입니다. 서버가 모든 결과를 정하고 클라이언트는 받은 결과를 그립니다. 이 구조에서는 렉이 대부분 느린 사람에게만 나타납니다.

  • 느린 본인은 스킬·줍기처럼 서버 확인이 필요한 행동이 핑만큼 늦는 입력 지연을 겪습니다. 이동은 예측으로 바로 보이지만 지터(도착 간격의 흔들림)가 크면 고무줄과 다른 사람의 순간이동까지 겪습니다.
  • 다른 사람은 느린 사람의 캐릭터가 멈칫하다 몰아서 움직이거나 순간이동하는 모습만 봅니다. 자기 조작과 몬스터 움직임은 멀쩡합니다. 핑만 높고 지터와 손실이 없으면 조금 늦은 위치에 매끄럽게 보일 뿐입니다. 남의 눈에 띄는 렉은 핑보다 지터와 손실이 만듭니다.
  • 특정 통신사·지역 회선만 나쁘면 그 사용자들이 한꺼번에 위 증상을 겪습니다. 서버 입장에서는 그 사람들의 입력만 들쭉날쭉 도착하므로, 이동 검증이나 핵 탐지에 오탐으로 걸리는 일도 그 사람들에게 몰립니다.
  • 특정 캐릭터로만 느리다면 회선보다 그 캐릭터의 데이터를 의심합니다. 아이템·우편이 수천 개 쌓인 캐릭터는 접속하고 저장할 때마다 남보다 몇 배를 읽고 씁니다. 같은 캐릭터로 다른 PC·회선에서 접속해도 똑같이 느린지 보면 가릴 수 있습니다.

하지만 느린 한 사람이 모두를 느리게 만드는 구조도 있습니다. 이런 구조에는 “누군가 그 사람을 기다린다”는 공통점이 있습니다.

  • 모두가 같은 턴을 기다리는 구조: 락스텝(RTS), 턴을 맞춰 진행하는 협동 콘텐츠. 한 명의 입력이 늦으면 전원이 멈춥니다. 지터 없이 늦기만 해도 모두의 입력이 가장 느린 사람의 핑만큼 늦게 반영됩니다.
  • 서버가 느린 사람에게 보내느라 기다리는 구조: 블로킹 전송(송신 버퍼에 여유가 생길 때까지 멈춰 기다리는 보내기), 동기 처리. 그 서버 스레드가 맡은 모두가 느려집니다. 보통은 사람마다 송신 대기열을 따로 두고 기다리지 않습니다. 이때 렉은 느린 사람에게만 나타나고 대기열이 너무 길어지면 그 사람만 접속이 끊깁니다.
  • 느린 사람이 중심 역할인 구조: 그 사람 PC가 호스트(방장)인 P2P(서버 없이 플레이어끼리 직접 연결)·리슨 서버(플레이어 PC가 서버를 겸함), 파티장 권한으로만 진행되는 이벤트. 서버 부하를 줄이려고 몬스터 이동 계산을 근처 플레이어의 클라이언트에 맡기는 게임이라면, 그 사람이 맡은 몬스터가 모두의 화면에서 뚝뚝 끊깁니다.
  • 판정이 느린 사람 기준으로 되감기는 구조: 지연 보상. 느린 사람은 공정하게 맞히지만 맞는 쪽은 “이미 숨었는데 맞았다”는 억울함을 겪습니다. 그래서 되감는 폭에 한도를 둡니다. 한도는 게임마다 다르며 대략 0.2초~1초 사이입니다(Source 엔진 기본값은 1초).

서버가 입력을 처리하는 방식에 따라 달라지는 모습

서버가 입력을 처리하는 방식느린 본인이 겪는 것다른 사람 눈에 비친 느린 사람다른 사람 자신의 게임
틱마다 모아서 처리
고정 틱, 받은 입력을 한꺼번에
스킬 결과가 핑과 틱 대기만큼 늦음 (입력 지연). 이동 검증이 엄격하면 고무줄멈칫했다 한 번에 여러 걸음 (몰아치기·순간이동). 지터 없이 핑만 높으면 매끄러움영향 없음
도착 즉시 처리
이벤트 방식, 받자마자 적용·전송
핑만큼 입력 지연. 틱을 기다리지 않는 만큼만 빠름이동은 빨라졌다 느려졌다 함 (약한 몰아치기). 몰려 온 스킬 여러 개가 한순간에 실행영향 없음
플레이어별 입력 버퍼
사람마다 모아 두고 한 틱에 하나씩
버퍼만큼 확정이 늦음비교적 매끄러움. 버퍼가 비면 잠깐 제자리영향 없음
지연 보상 판정
공격자가 본 시점으로 되감기
조준한 대로 맞음 (되감기 한도 안에서)숨은 뒤에도 그 사람의 공격이 맞음억울한 피격 (번짐)
락스텝·턴 대기입력 지연. 입력이 늦으면 멈춤모두 멈춤멈춤. 늦기만 해도 입력 지연 (전원에게 번짐)
블로킹 전송·동기 처리
서버가 그 사람을 기다림
멈춤 뒤 몰아치기그 서버 스레드가 맡은 모두가 느려짐슬로우모션·멈춤 (그 스레드가 맡은 사람들에게 번짐)
느린 사람이 호스트
P2P, 리슨 서버
본인은 핑 0모두의 화면이 뚝뚝 끊김전원 렉
몬스터 제어를 느린 사람이 맡음
몬스터 이동 계산을 클라이언트에 맡김
본인 화면의 몬스터는 멀쩡그 사람이 맡은 몬스터가 멈칫하다 순간이동그 몬스터와 싸우는 모두 (번짐)

같은 PC의 두 클라이언트, 한쪽만 NPC가 안 보일 때

같은 사람이 같은 PC에서 클라이언트 두 개를 띄웠는데 한쪽만 NPC가 안 보인다면, 회선은 거의 원인이 아닙니다. 두 클라이언트는 같은 공유기, 같은 회선을 씁니다. 세 군데에서 차이가 생깁니다.

  1. 서버가 그 클라이언트에게 안 보냈다: 채널·인스턴스·퀘스트 페이즈(진행도에 따라 보이는 NPC를 나누는 기능)가 다름, 시야 등록 순서 꼬임, 연결별 전송량 한도, 같은 PC·같은 IP를 한 사람으로 인식하는 세션 버그, 멀티 클라이언트 제한.
  2. 보냈는데 클라이언트가 버렸다: 로딩 중에 도착한 등장 알림 폐기, 입장 직후 몰린 등장 정보가 수신 버퍼 넘침·비신뢰(unreliable) 채널(잃어도 다시 보내지 않는 채널) 때문에 사라짐, 기준 스냅샷(변화분만 보낼 때 출발점이 되는 전체 정보) 유실, ID가 재사용된 새 NPC를 옛 NPC로 오인, 고정 UDP 포트 충돌로 다른 클라이언트가 가로챔, 백그라운드 창이라 처리가 밀려 수신 버퍼가 넘침, 서버 시각 추정이 어긋나 표시를 미룸.
  3. 받았는데 그리지 못했다: 두 클라이언트가 같은 캐시 파일을 동시에 써서 모델 로딩 실패, 그래픽 메모리(VRAM) 부족, 표시 인원 제한 같은 옵션 차이, 버전·데이터 불일치.

먼저 볼 단서는 세 가지입니다. 이름표는 있는데 캐릭터 모델만 없는가(서버는 보냈고 그리기 실패), 시야를 벗어났다 돌아오면 보이는가(등장 알림 하나가 빠짐), 그리고 안 보이는 쪽 창을 앞으로 가져오면 나아지는가(백그라운드 창의 처리 제한). 반대로 이미 죽은 몬스터가 내 화면에만 서 있는 “유령 개체”는 퇴장 알림이 빠져서 생깁니다.

일부에게만 생기는 문제

느린 사람이 남의 화면에서 몰아서 움직임 Laggy player seen by others (bursty inputs)

회선이 나쁜 사람의 입력은 들쭉날쭉 몰려서 서버에 도착합니다. 서버가 틱마다 받은 만큼 적용하면, 다른 사람 눈에는 그 캐릭터가 멈칫했다가 한 번에 여러 걸음을 갑니다.

왜: 느린 사람의 이동 명령이 어떤 틱엔 0개, 어떤 틱엔 2~3개씩 도착 → 그러면: 서버가 받은 틱에 한꺼번에 적용해 그 캐릭터 위치가 계단처럼 변함 → 화면에서는: 다른 사람 화면에서 그 캐릭터만 멈칫하다 한 번에 몰아서 이동. 나머지는 멀쩡

증상: 몰아치기, 순간이동 · 주 담당 게임개발팀·서버 개발 · 함께 외부·외부

도착 즉시 처리하는 서버의 몰아치기 Event-driven processing of bursty inputs

패킷이 도착하는 대로 바로 처리하고 알리는 서버에서는, 느린 사람의 몰려 온 행동이 연달아 즉시 실행됩니다.

왜: 느린 사람의 스킬·이동 요청이 몰려서 도착 → 그러면: 서버가 받는 즉시 순서대로 실행하고 바로 모두에게 알림 → 화면에서는: 다른 사람 눈에 그 사람이 스킬 여러 개를 한순간에 쓰거나 빨리 감기처럼 움직임

증상: 몰아치기 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

플레이어별 입력 버퍼 크기 Per-player server input buffer (jitter buffer)

서버가 사람마다 입력을 조금 모아 두었다가 한 틱에 하나씩 꺼내 쓰면, 다른 사람 눈에는 매끄럽지만 본인 행동이 서버에서 확정되는 시점은 그만큼 늦어집니다.

왜: 서버가 느린 사람의 입력을 버퍼에 모아 한 틱에 하나씩 적용 → 그러면: 버퍼가 작으면 자주 비어 그 캐릭터가 제자리에 서거나 서버가 마지막 입력으로 추측해 움직이고, 크면 본인 입력이 늦게 확정 → 화면에서는: 작으면 남 눈에 멈칫, 크면 본인의 스킬 결과가 늦게 나옴(입력 지연)

증상: 뚝뚝 끊김, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

특정 통신사 사용자에게 몰리는 검증 오탐 Anti-cheat / movement validation false positives on bad ISPs

지터가 큰 회선을 쓰는 사람들은 입력이 몰려 도착해서 서버의 속도·쿨타임 검사에 자주 걸립니다.

왜: 특정 통신사·지역 회선의 지터가 저녁에 커짐 → 그러면: 몰려 도착한 정상 입력을 서버가 과속·쿨타임 위반으로 판단 → 화면에서는: 그 통신사 사용자만 고무줄, 스킬 거절, 심하면 서버가 내보내 접속 끊김

증상: 고무줄, 씹힘·롤백, 접속 끊김 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·네트워크 인프라

느린 파티원 한 명과 보스 기믹 One laggy member in a synchronized mechanic

모두가 정해진 순간에 함께 반응해야 하는 레이드 기믹에서는, 느린 한 사람의 늦은 반응이 파티 전체의 실패가 됩니다.

왜: “모두 동시에 흩어지기”, “한 명이 버튼 누르기” 같은 공동 기믹 → 그러면: 느린 사람은 예고를 늦게 보고 입력도 늦게 도착 → 화면에서는: 그 사람 한 명 때문에 전멸, 다른 파티원은 “렉 걸린 사람 때문”이라고 느낌

증상: 씹힘·롤백, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

몬스터 제어 권한이 느린 클라이언트에 있음 Monster movement delegated to a player client

서버 부하를 줄이려고 몬스터 이동 계산을 근처 플레이어 한 명의 클라이언트에 맡기는 게임이 있습니다. 그 사람 회선이 나쁘면 그 몬스터가 모두의 화면에서 이상하게 움직입니다.

왜: 서버가 몬스터 이동 계산을 가장 가까운(또는 먼저 온) 플레이어의 클라이언트에 맡김 → 그러면: 맡은 사람의 결과 보고가 늦거나 몰려서 서버에 도착 → 화면에서는: 그 몬스터만 주변 모두의 화면에서 멈칫하다 순간이동. 맡은 사람 본인 화면에서는 멀쩡

증상: 순간이동, 뚝뚝 끊김, 몰아치기 · 주 담당 게임개발팀·서버 개발

특정 캐릭터의 데이터가 비대함 One character with oversized data (inventory, mail, buffs)

아이템·우편이 수천 개 쌓였거나 친구·차단 목록, 버프가 유난히 많은 캐릭터는 접속하고 저장하고 주변에 알릴 양이 남보다 몇 배 큽니다. 회선과 상관없이 그 캐릭터로만 느립니다.

왜: 오래 키운 캐릭터나 이벤트 보상이 인벤토리·우편함에 수천 개 쌓임 → 그러면: 접속·지역 이동·저장 때마다 그만큼 DB를 읽고 쓰고 주변에 보낼 장비·버프 정보도 큼 → 화면에서는: 그 캐릭터만 입장 로딩이 길고 인벤토리·우편을 열 때 멈칫. 저장을 게임 스레드에서 기다리는 서버라면 주변 사람까지 잠깐 멈춤

증상: 접속 불가·무한 로딩, 입력 지연, 멈춤 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

채널·인스턴스·페이즈 차이 Different channel / instance / phase

두 캐릭터가 다른 채널이나 인스턴스에 있거나, 퀘스트 진행도에 따라 보이는 NPC가 다른 “페이즈”에 있으면 서로 다른 세상을 봅니다.

왜: 두 번째 캐릭터가 다른 채널로 배정되거나 퀘스트 단계가 다름 → 그러면: 서버가 그 캐릭터에게는 해당 NPC를 보내지 않음(정상) → 화면에서는: 한쪽에만 NPC가 없음. 버그처럼 보이지만 설계대로

증상: 안 보임·유령 개체 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

로딩 중 도착한 등장 알림 폐기 Spawn messages dropped before the client is ready

존에 들어가자마자 서버가 주변 NPC 등장 알림을 보내는데 클라이언트가 아직 맵을 불러오는 중이라 그 알림을 버립니다.

왜: 서버가 입장 처리 직후 주변 개체 등장 알림을 발송 → 그러면: 클라이언트는 로딩 중이라 메시지 핸들러가 아직 없어 알림을 버림 → 화면에서는: 서버는 이미 보낸 것으로 처리해 다시 안 보냄. 시야를 벗어났다 오기 전까지 NPC가 안 보임

증상: 안 보임·유령 개체 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

시야 등록 순서 꼬임 Interest-management race on enter/leave

캐릭터가 시야 격자에 등록되는 순간과 NPC가 격자를 옮기는 순간이 겹치면, 그 NPC의 등장 알림이 누락될 수 있습니다.

왜: 입장·채널 이동·순간이동 처리와 NPC 이동이 같은 순간에 겹침 → 그러면: “새로 보이게 된 개체” 계산에서 그 NPC가 빠짐 → 화면에서는: 특정 NPC 몇 마리만 안 보이거나 이미 떠난 NPC가 남아 있음

증상: 안 보임·유령 개체 · 주 담당 게임개발팀·서버 개발

기준 스냅샷 유실 Lost baseline for delta compression

서버가 “지난번과 달라진 것만” 보내는 방식에서, 처음 한 번 보내는 전체 정보(기준)를 잃으면 그 뒤 변화분을 적용할 수 없습니다.

왜: 개체의 전체 정보(기준) 패킷이 손실되거나 처리 전에 버려짐 → 그러면: 클라이언트가 이후의 변화분을 적용할 대상이 없어 무시 → 화면에서는: 그 개체가 안 보이거나, 한참 뒤 갑자기 나타남

증상: 안 보임·유령 개체, 순간이동 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

퇴장 알림 유실 (유령 개체) Missed despawn (ghost entity)

“사라졌다”는 알림을 놓치면, 이미 죽었거나 떠난 NPC·플레이어가 내 화면에만 남습니다.

왜: 죽음·퇴장·시야 이탈 알림이 손실되거나 순서가 꼬임 → 그러면: 클라이언트는 그 개체가 아직 있다고 판단 → 화면에서는: 때려도 반응 없는 몬스터, 이미 나간 플레이어가 서 있음

증상: 안 보임·유령 개체 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

입장 직후 몰리는 등장 정보 유실 Initial spawn burst lost (unreliable channel, receive buffer, fragmentation)

존에 들어서는 순간 서버는 주변 개체 수십~수백 개의 등장 정보를 한꺼번에 보냅니다. 이 정보를 비신뢰(unreliable) 채널로 보내거나, 로딩 중이라 소켓을 못 읽는 사이 수신 버퍼가 넘치면 일부가 사라지고 다시 오지 않습니다.

왜: 입장 직후 등장 정보가 짧은 순간에 몰려 도착 → 그러면: 로딩 중인 클라이언트가 소켓을 늦게 읽어 OS 수신 버퍼가 넘치거나, 큰 UDP 패킷이 단편화되어 프래그먼트 하나만 잃어도 통째로 사라짐. 비신뢰 채널이면 다시 보내 주지도 않음 → 화면에서는: 로딩이 느린 쪽 클라이언트에서만 NPC 몇 마리가 빠짐. 시야를 벗어났다 돌아오면 보임

증상: 안 보임·유령 개체 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

개체 ID 재사용 혼동 Entity ID reused without a generation counter

죽은 NPC가 다시 나타날 때 서버가 같은 개체 ID를 다시 쓰면, 그 사이 퇴장 알림을 놓친 클라이언트는 새 NPC를 옛 NPC로 오인합니다.

왜: NPC가 죽고 같은 개체 ID로 다시 등장 → 그러면: 퇴장 알림을 놓친 클라이언트는 “이미 아는 개체”라며 등장 알림을 무시하거나 죽은 상태를 그대로 둠 → 화면에서는: 한쪽 화면에만 NPC가 없거나 쓰러진 채로 보임, 다른 NPC의 모습으로 보이기도 함

증상: 안 보임·유령 개체 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

고정 UDP 포트 충돌 Two clients bound to the same local UDP port

클라이언트가 정해진 로컬 포트를 쓰도록 만들어져 있으면, 같은 PC의 두 번째 클라이언트는 포트를 못 쓰거나 첫 번째와 패킷을 나눠 받습니다.

왜: 두 클라이언트가 같은 로컬 UDP 포트를 열려고 함(재사용 옵션으로 억지로 공유) → 그러면: OS가 들어온 패킷을 한쪽 소켓에만 넘기거나, 어느 쪽이 받을지 보장하지 않음. 공유기와 서버도 두 클라이언트를 같은 주소로 봄 → 화면에서는: 한쪽은 월드 패킷을 못 받아 NPC·다른 플레이어가 안 보이거나 접속이 끊김

증상: 안 보임·유령 개체, 접속 끊김, 접속 불가·무한 로딩 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

IP·기기 기준 세션 구분 버그 Session keyed by IP or machine ID

서버나 중간 서버가 연결을 IP나 기기 ID로 구분하면, 같은 PC(같은 공인 IP)의 두 클라이언트를 한 사람으로 인식합니다.

왜: 세션 테이블을 IP 또는 IP+기기 ID로 만듦 → 그러면: 두 번째 클라이언트의 정보가 첫 번째 세션에 덮어써지거나 섞임 → 화면에서는: 한쪽은 NPC가 안 보이고 다른 쪽은 접속이 끊기거나 남의 정보를 받음

증상: 안 보임·유령 개체, 접속 끊김 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

멀티 클라이언트 제한 Multi-client restriction policy

보안 모듈이나 서버 정책이 한 PC의 여러 클라이언트를 제한하면, 두 번째 클라이언트는 실행·접속이 막히거나 먼저 켠 쪽의 접속이 끊깁니다. 일부 게임은 추가 클라이언트의 기능만 막습니다.

왜: 보안 모듈이 중복 실행을 감지, 또는 서버가 같은 기기의 추가 접속을 제한 → 그러면: 두 번째 실행·접속을 거절하거나 한쪽을 끊음. 드물게 추가 클라이언트의 일부 기능만 차단 → 화면에서는: 접속 불가나 한쪽 접속 끊김. 기능만 막는 게임에서는 한쪽만 NPC·상점이 안 보임

증상: 접속 불가·무한 로딩, 안 보임·유령 개체, 접속 끊김 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

백그라운드 창의 처리 제한 Background window throttling

클라이언트 창이 백그라운드에 있으면 게임·엔진·OS가 그 클라이언트의 프레임과 처리를 줄입니다. 받은 패킷을 제때 처리하지 못해 밀리거나 넘칩니다.

왜: 게임 옵션이나 그래픽 드라이버의 백그라운드 프레임 제한(예: NVIDIA 드라이버는 초당 20~200 중에서 지정), 절전, 엔진의 백그라운드 정지 설정. OS도 앞에 있는 창(포그라운드)에 CPU·GPU를 우선 배정 → 그러면: 프레임마다 처리하는 패킷 수가 줄어 대기열이 쌓이고 수신 버퍼가 넘치면 버려짐 → 화면에서는: 창을 앞으로 가져오면 몰아서 나타나거나, 일부 NPC가 끝내 안 보임

증상: 안 보임·유령 개체, 몰아치기, 접속 끊김 · 주 담당 게임개발팀·클라이언트 개발 · 함께 외부·외부

캐시·에셋 파일 동시 접근 충돌 Shared cache / asset file lock conflicts

두 클라이언트가 같은 캐시 폴더에 동시에 쓰거나 파일을 잠그면, 한쪽이 NPC 모델·텍스처를 못 불러옵니다.

왜: 두 클라이언트가 같은 설치 폴더의 캐시·패치 파일을 동시에 씀 → 그러면: 파일 잠금 실패나 반쯤 쓰인 파일을 읽어 로딩 실패 → 화면에서는: 이름표는 있는데 캐릭터 모델이 없거나 투명한 NPC

증상: 안 보임·유령 개체 · 주 담당 게임개발팀·클라이언트 개발

메모리·VRAM 부족으로 스트리밍 실패 Memory / VRAM exhaustion

클라이언트 두 개가 그래픽 메모리를 나눠 쓰면, 새로 필요한 모델·텍스처를 올릴 자리가 없어 일부가 안 그려집니다.

왜: 두 클라이언트가 VRAM·RAM을 나눠 씀. OS는 백그라운드 창의 그래픽 메모리 할당량을 먼저 줄이기도 함 → 그러면: 엔진이 새 모델·텍스처를 올리지 못하거나 계속 내렸다 올림 → 화면에서는: NPC가 늦게 나타나거나 흐릿하거나 안 보임, 뚝뚝 끊김

증상: 안 보임·유령 개체, 뚝뚝 끊김 · 주 담당 게임개발팀·클라이언트 개발 · 함께 외부·외부

표시 옵션 차이 Different display settings

표시 인원 제한, NPC 이름표·모델 숨김, 저사양 모드 같은 옵션이 두 클라이언트에서 다르면 보이는 것이 다릅니다.

왜: 한쪽 클라이언트만 “주변 캐릭터 표시 수 제한”이나 저사양 모드 → 그러면: 멀리 있거나 우선순위 낮은 NPC를 그리지 않음(정상) → 화면에서는: 한쪽에만 NPC가 없음

증상: 안 보임·유령 개체 · 주 담당 게임개발팀·클라이언트 개발

클라이언트 버전·데이터 불일치 Client version / data table mismatch

두 번째 클라이언트가 다른 설치본이거나 패치가 덜 되었으면, 서버가 보낸 새 NPC ID를 몰라 조용히 무시합니다.

왜: 다른 폴더의 설치본, 또는 패치 중 실행한 클라이언트 → 그러면: 모르는 NPC ID·모델 ID를 받으면 건너뜀 → 화면에서는: 새로 추가된 NPC만 한쪽에 안 보임

증상: 안 보임·유령 개체 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

연결별 전송 예산·우선순위 Per-connection bandwidth budget and priority

서버가 연결마다 보낼 양에 한도를 두고 가까운 것부터 보내면, 한도가 낮게 잡힌 쪽은 멀리 있는 NPC를 늦게 받거나 못 받습니다.

왜: 사람 많은 곳에서 서버가 연결별 전송량 한도 안에서 중요도 순으로 전송 → 그러면: 대역폭 추정이 낮게 잡힌 연결(예: 백그라운드 창이라 수신 확인이 늦은 쪽)은 뒤쪽 개체를 계속 미룸 → 화면에서는: 멀리 있는 NPC가 한쪽에서만 늦게 보이거나 안 보임

증상: 안 보임·유령 개체, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

시계 추정 오차로 개체 보류 Clock estimate error holds or discards entities

클라이언트가 추정한 서버 시각이 틀리면, 막 도착한 개체 정보를 “아직 미래”라며 보류하거나 “너무 옛날”이라며 버립니다.

왜: 한쪽 클라이언트의 서버 시각 추정이 크게 어긋남(로딩 중 측정, 절전 복귀) → 그러면: 보간 기준 시각과 개체 정보 시각이 맞지 않음 → 화면에서는: 개체가 늦게 나타나거나 멈춘 채로 보임

증상: 안 보임·유령 개체, 뚝뚝 끊김 · 주 담당 게임개발팀·클라이언트 개발

06자주 보는 원인

TCP 재전송: 생기는 원인과 지연이 커지는 이유

서버 지표에 “TCP 재전송(Retransmission)”이 늘면 렉 제보도 함께 느는 경우가 많습니다. 재전송은 “패킷이 사라졌다” 또는 “사라졌다고 잘못 판단했다”는 신호입니다. 원인은 와이파이부터 서버 네트워크 카드까지 경로 어디에나 있고 게임처럼 작은 패킷을 드문드문 보내는 연결에서는 패킷 하나만 잃어도 수백 ms 멈춤으로 번집니다. 이 장은 재전송의 근본 원인, 원인을 찾는 방법, 해결 방향을 정리합니다.

서버가 보냄게임이 받음123×사라짐456124563다시 보낼 때까지 기다림 (복구 방식에 따라 다름)3게임에는 아무것도 안 옴: 멈춤3·4·5·6이 한꺼번에: 몰아치기
50ms마다 보내는 연결에서 3번 하나가 사라진 경우입니다. TCP는 순서대로만 넘겨주므로 4·5·6번이 도착해도 3번을 다시 받을 때까지 게임에 넘기지 않습니다. 그래서 손실 하나가 멈춤과 그 뒤의 몰아치기가 됩니다. 다시 보내는 시점은 복구 방식에 따라 왕복 한 번 안팎에서 “왕복 시간 + 최소 200ms”(재전송 타이머)까지 달라집니다(아래 “재전송의 종류”).

재전송이 게임을 느리게 만드는 네 가지 이유

  1. 순서 대기(HOL 블로킹): TCP는 잃어버린 하나를 다시 받을 때까지 뒤에 도착한 패킷을 게임에 넘기지 않습니다. 하나를 잃으면 그 뒤 전부가 함께 멈췄다가 한꺼번에 풀립니다(멈춤 뒤 몰아치기).
  2. 재전송 대기 시간: 보내는 쪽은 재전송 타이머(RTO)가 끝나야 다시 보냅니다. 리눅스 기준으로 “왕복 시간 + 최소 200ms”입니다. 다시 보낸 것도 잃으면 기다림이 두 배씩 늘어납니다(0.3초 → 0.6초 → 1.2초 …).
  3. thin stream(작은 패킷을 드문드문 보내는 연결): 빠른 재전송은 받는 쪽이 “뒤따르는 패킷 3개가 도착했다”고 알리는 신호(중복 ACK 3개. ACK는 “받았다”는 확인)로 작동합니다. 게임 패킷은 50~200ms에 하나씩이라 신호가 모이기 전에 RTO가 먼저 오는 경우가 많습니다. 대용량 다운로드는 잘 버티는데 게임만 유독 멈추는 이유입니다. 최신 리눅스의 RACK은 뒤따르는 패킷 하나만 도착해도 판단해 이 차이를 크게 줄이지만, 패킷 간격이 200ms 안팎으로 길면 RACK도 RTO보다 빠르지 않습니다.
  4. 전송량 축소: TCP는 손실을 혼잡 신호로 보고 한 번에 보낼 양(혼잡 윈도우)을 줄입니다. RTO까지 가면 한 번에 하나만 보내는 상태에서 다시 늘려야 합니다. 그동안 새로 생긴 패킷은 서버에 쌓여 기다리고 사람 많은 곳의 큰 업데이트가 줄줄이 밀립니다.

재전송의 종류

종류언제 일어나나복구까지 걸리는 시간게임에서 보이는 모습
빠른 재전송
Fast retransmit
뒤따르는 패킷이 먼저 도착해 받는 쪽이 “중간이 빠졌음”(중복 ACK·SACK)을 알릴 때왕복 시간 + 뒤따르는 패킷 3개가 도착하는 시간짧은 멈칫. 패킷이 촘촘할수록 빠름
RACK·TLP
시간 기준 손실 판단, 끝 패킷 재전송
나중에 보낸 패킷이 도착했는데 앞의 것이 일정 시간 안 올 때, 또는 한동안 ACK가 없을 때 끝 패킷을 한 번 더 보냄뒤 패킷의 확인이 오면 곧(RACK. 순서만 바뀐 것일 수 있어 왕복 시간의 1/4쯤 더 기다림). 뒤 패킷이 없으면 왕복 시간의 약 2배(TLP), 아직 확인받지 못한 패킷이 하나뿐이면 지연 ACK를 감안해 200ms를 더 기다림thin stream에서도 비교적 짧은 멈칫. 최신 리눅스 기본
RTO 재전송
Retransmission timeout
아무 신호 없이 기다림이 끝났을 때왕복 시간 + 최소 200ms, 실패할 때마다 두 배수백 ms~수 초 멈춤 뒤 몰아치기, 길어지면 접속 끊김
SYN 재전송접속 요청 자체가 사라졌을 때 (접속 대기열(backlog) 넘침, 방화벽 차단)1초, 2초, 4초, 8초 … (리눅스 6.5 이상은 다섯 번까지 1초 간격으로 다시 보낸 뒤 두 배씩, 예전 윈도우는 3초부터)접속 버튼 뒤 1초, 3초처럼 초 단위로 딱 떨어지게 늦고 계속 실패하면 접속 불가·무한 로딩
불필요한 재전송
Spurious retransmission
잃지 않았는데 늦게 오거나 순서가 바뀌어 잃은 줄 알고 다시 보냄복구할 게 없음. 대신 전송량만 줄어듦(리눅스는 DSACK(받는 쪽의 “이미 받았음” 알림)·타임스탬프로 감지하면 되돌리기도 함)회선 낭비, 대용량 전송 속도 저하. 지표상 재전송률만 높음
제로 윈도우 프로브
재전송과 헷갈리는 것
받는 쪽 버퍼가 꽉 차 “잠깐 보내지 마” 상태일 때 확인용으로 보내는 패킷받는 쪽이 읽기 시작할 때까지멈춤. 회선은 멀쩡하고 받는 쪽 프로그램이 제때 읽지 못한 것

어디서 잃었는지 찾는 법

재전송률은 “보낸 패킷 중 다시 보낸 비율”입니다. 부팅 뒤 쌓인 누적값은 평소 값에 묻히므로, 1분처럼 일정한 간격 동안 늘어난 양으로 계산합니다. 공인된 기준은 없지만 서버 전체 평균의 대략적인 감각은 0.1% 아래면 건강, 0.1~1%면 일부 유저가 가끔 멈칫, 1%를 넘으면 많은 유저가 체감, 3%를 넘으면 심각입니다. 모바일·해외 유저가 많은 게임은 평소 값이 더 높게 나옵니다. 그래서 숫자 하나로 판단하기보다 평소 대비 몇 배 늘었는지를 함께 봅니다. 평균은 소수의 나쁜 회선에 끌려가므로 지역·통신사·서버·시간대별로 나눠 보는 것이 원인을 찾는 지름길입니다. 연결을 중간에서 받아 서버로 새로 이어 주는 장비(프록시, 일부 로드밸런서·게이트웨이)가 있으면 게임 서버 지표에는 그 장비와 서버 사이 구간만 잡힙니다. 유저 쪽 재전송은 그 장비에서 봅니다.

어디서 보나무엇을 보나무엇을 알 수 있나
서버 전체 (리눅스)nstat을 1분 간격으로 두 번 실행한 증가분: TcpRetransSegs ÷ TcpOutSegs, 그리고 TcpExt 계열의 TCPTimeouts, TCPLossProbes·TCPLossProbeRecovery, TCPLostRetransmit, TCPSpuriousRTOs, TCPDSACKRecv, TCPSynRetrans재전송률, RTO까지 간 횟수, TLP를 보낸 횟수와 그중 실제 손실을 메운 횟수, 다시 보낸 것까지 또 잃은 횟수, 접속 요청 재전송. DSACK·Spurious가 많으면 “잃지 않았는데 다시 보냄”. 리눅스 OutSegs에는 재전송분이 빠져 있어 엄밀한 비율은 RetransSegs ÷ (OutSegs + RetransSegs)지만, 1% 안팎에서는 차이가 작습니다
연결별 (리눅스)ss -ti의 retrans(지금 복구 중/누적), rto, backoff, rtt, cwnd, lost, reordering, bytes_retrans특정 사용자·지역만 재전송이 많은지, RTO가 얼마나 늘어나 있는지(backoff는 RTO가 연달아 두 배가 된 횟수). bytes_retrans ÷ bytes_sent가 그 연결의 재전송률
재전송 한 건씩 (리눅스)eBPF 도구 tcpretrans(bcc). -c는 연결별 집계, -l은 TLP 포함재전송이 날 때마다 상대 IP·포트·연결 상태를 한 줄씩 보여 줍니다. 패킷 캡처 없이 가볍게, 어느 유저 대역·서버에 몰리는지 확인
서버 네트워크 카드ip -s -s link의 dropped·missed·crc, ethtool -S의 rx_missed_errors·rx_no_buffer_count·rx_crc_errors 등(이름은 드라이버마다 다름, mlx5는 rx_out_of_buffer·rx_discards_phy), /proc/net/softnet_stat의 2번째 열(dropped)·3번째 열(time_squeeze)서버 네트워크 카드가 받자마자 버렸는지(링 버퍼·CPU), 선이나 광모듈 불량(CRC)인지. softnet_stat은 CPU마다 한 줄이고 16진수입니다. time_squeeze가 계속 늘면 수신 처리 코어가 제시간에 일을 못 끝내는 것
클라우드 네트워크AWS ENA는 ethtool -S의 bw_in_allowance_exceeded, bw_out_allowance_exceeded, pps_allowance_exceeded, conntrack_allowance_exceeded, linklocal_allowance_exceeded. 기본 CloudWatch 화면에는 없어 CloudWatch 에이전트로 따로 모읍니다인스턴스 한도에서 조용히 버렸는지. 값이 늘고 있으면 한도 초과입니다. 다른 클라우드도 VM 크기별 대역폭·연결 수 한도가 있습니다
스위치·라우터·방화벽포트의 CRC·입력 오류, 출력 드롭, 폴리서 초과, 세션 테이블 사용량, 드롭 로그데이터센터 장비 구간에서 버렸는지. 5분 평균 사용률이 낮은데 출력 드롭이 늘면 마이크로버스트(아주 짧은 순간의 트래픽 몰림)
경로mtr·pathping으로 끝까지 이어지는 손실. 수백 번 이상 보내야 1% 안팎의 손실이 보이고 게임과 같은 TCP 포트로 보내면(mtr -T -P PORT) 더 정확합니다몇 번째 구간부터 손실이 시작되는지. 중간 한 구간만 손실로 보이고 뒤는 멀쩡하면 그 장비가 측정용 응답(ICMP)을 제한하는 것일 뿐입니다. 오가는 경로가 다를 수 있어 서버 쪽에서 유저 쪽으로도 측정합니다
패킷 캡처 (양쪽 끝)Wireshark 필터 tcp.analysis.retransmission, 같은 tcp.analysis. 계열의 fast_retransmission, spurious_retransmission, duplicate_ack, lost_segment, zero_window원본 패킷이 보낸 쪽 캡처에는 있고 받은 쪽에는 없으면 그 사이에서 잃은 것. 받은 쪽에도 있으면 불필요한 재전송이거나 ACK가 돌아오다 늦거나 사라진 것. 받는 서버의 링 버퍼에서 버린 패킷도 캡처에는 “사이에서 잃음”으로 보이니 네트워크 카드 카운터와 함께 봅니다
윈도우 서버성능 모니터의 TCPv4\Segments Retransmitted/sec ÷ Segments Sent/sec, Network Interface\Packets Received Discarded, netsh int tcp show global, pktmon(윈도우 10 1809·서버 2019 이상에 내장)재전송률 추이, 네트워크 카드가 받자마자 버렸는지, TCP 설정, 윈도우 안 어디에서 버렸는지

확인 순서: 인프라팀과 함께 볼 때는 아래 순서가 빠릅니다.

  1. 언제·누구에게: 재전송률이 언제부터 늘었는지, 특정 지역·통신사·서버·시간대에 몰리는지 봅니다.
  2. 진짜 손실인지: TCPSpuriousRTOs·DSACK이 함께 늘면 늦게 도착한 것을 잃은 줄 안 불필요한 재전송을 먼저 의심합니다.
  3. 서버 수신 단계: 같은 시각에 네트워크 카드·softnet·클라우드 한도 카운터가 늘었다면 서버 쪽에서 버린 것입니다.
  4. 데이터센터 장비: 스위치·방화벽의 드롭·CRC 카운터와 세션 테이블을 봅니다.
  5. 바깥 경로: 문제 유저 쪽과 서버 쪽 양방향 mtr로 손실이 시작되는 구간을 찾습니다.
  6. 그래도 모르면: 양쪽 끝에서 같은 시각에 패킷을 캡처해 비교합니다.

제보에 시각(초 단위), 유저의 통신사·지역, 접속 서버, 증상 이름이 있으면 인프라팀이 이 순서를 바로 밟을 수 있습니다.

해결 방향

1. 잃지 않게 (근본 해결)

  • 와이파이 대신 유선, 5GHz·6GHz, 공유기 SQM·ECN으로 대기열 넘침 줄이기
  • 서버가 한 틱의 업데이트를 한꺼번에 쏘지 않게 틱 안에 나눠 보내기. 연결 하나가 몰아 보내는 것은 페이싱(fq, BBR, 전송 속도 상한)으로 고르게
  • 링 버퍼 늘리기, 인터럽트를 여러 코어에 분산, 클라우드 한도 확인
  • CRC 오류가 있는 선·광모듈 교체, 듀플렉스 설정 맞추기
  • 폴리서(초과분 즉시 버림) 대신 셰이퍼(대기열에 넣었다가 천천히 내보냄), 허용 버스트 늘리기
  • 방화벽·연결 추적(conntrack) 테이블과 중간 장비의 초당 패킷 수에 여유 두기, 오가는 경로가 같은 방화벽을 지나게 맞추기
  • MSS(패킷 하나에 담는 데이터의 최대 크기) 조정과 크기 초과 알림(ICMP) 허용으로 MTU 블랙홀 막기(MTU 탐색은 마지막 안전망), 클라이언트가 보내는 하트비트로 NAT·LB 매핑 유지

2. 빨리 복구하게

  • SACK·타임스탬프가 서버 설정에서 꺼져 있거나 중간 장비에서 지워지지 않게 확인(SACK이 없으면 RACK-TLP도 동작하지 않음)
  • RACK-TLP 사용(최신 리눅스·안드로이드 기본). 내 입력처럼 클라이언트가 보내는 쪽은 클라이언트 OS가 복구하므로 서버 설정으로는 바뀌지 않음(윈도우는 10(1607)·서버 2016부터 TLP와 RACK이 기본으로 켜져 있고, 잃은 재전송까지 복구하는 새 RACK은 서버 2022부터)
  • thin stream용 tcp_thin_linear_timeouts, 리눅스 6.15 이상은 TCP_RTO_MAX_MS로 RTO 상한 낮추기
  • 게임 연결은 TCP_NODELAY를 켜 두기(Nagle이 새 패킷을 보내지 않고 모아 두면 RACK이 쓸 뒤따르는 패킷이 사라짐)
  • 내부망 서버 간 연결은 경로별 RTO 최소값을 낮추기(ip route … rto_min)
  • TCP_USER_TIMEOUT과 게임 하트비트로 죽은 연결을 빨리 끊고 재접속

3. 재전송에 덜 민감하게 (구조)

  • 실시간 위치·전투는 UDP 위에서 필요한 것만 다시 보내기(옛 위치는 다시 보낼 가치가 없음). 입력은 최근 몇 개를 겹쳐 보내면 하나를 잃어도 다음 패킷이 메움
  • 채팅·거래처럼 순서가 필요한 것과 실시간 패킷을 다른 흐름으로 분리(QUIC 스트림, TCP 연결 나누기 등). 한쪽의 손실이 다른 쪽을 막지 않음
  • TCP를 계속 쓴다면 보내기 버퍼에 옛 위치를 쌓지 말고 최신 상태로 덮어쓰기(TCP_NOTSENT_LOWAT 등). 긴 멈춤 뒤 몰아치기가 짧아짐
  • 보간 버퍼와 예측으로 짧은 멈칫을 화면에서 가리기. 수백 ms짜리 RTO 멈춤까지 가리기는 어려움

설정 이름 정리: 켤 설정과 헷갈리기 쉬운 설정

재전송 복구에 관련된 설정은 대부분 운영체제(커널) 설정이고 게임 연결에만 따로 켤 수 있는 소켓 옵션은 몇 개뿐입니다. 이름 때문에 자주 헷갈리는 TCP_NODELAY는 복구를 빠르게 하는 설정은 아닙니다. 다만 켜지 않으면(Nagle 사용) 복구 중에 새 패킷이 더 늦어집니다. 아래는 리눅스 기준이며 윈도우는 이름과 지원 범위가 다릅니다.

설정어디서무엇을 바꾸나주의
TCP_NODELAY소켓 옵션Nagle 끄기. 작은 메시지를 모으지 않고 바로 보냄손실이 없어도 생기는 40~200ms 대기를 없앰. 재전송 타이머(RTO) 자체는 그대로. 다만 Nagle이 켜져 있으면 복구를 기다리는 동안 새 패킷까지 묶여 복구 뒤 한 왕복을 더 기다리고, 빠른 재전송·RACK이 기대는 뒤따르는 패킷도 사라져 RTO까지 가기 쉬움. 게임은 켜는 것이 보통
net.ipv4.tcp_recovery (RACK)커널 설정시간 기준 손실 판단. 순서 뒤바뀜에 강하고 thin stream도 빨리 복구기본값 1(켜짐). 리눅스 4.4에 들어와 4.18 무렵 지금 모습이 됨. 6.17부터는 RACK이 유일한 손실 판단 방식이라 0으로 바꿔도 효과가 없음. SACK이 없는 연결에서는 작동하지 않음
net.ipv4.tcp_early_retrans (TLP)커널 설정한동안(왕복 시간의 약 2배) ACK가 없으면 끝 패킷을 한 번 더 보내 마지막 패킷들의 손실(tail loss)을 빨리 발견기본값 3(켜짐), 0이면 꺼짐. SACK이 있어야 작동. 아직 ACK를 받지 못한 패킷(in-flight)이 하나뿐이면 200ms를 더 기다려 RTO와 비슷해짐
net.ipv4.tcp_sack, tcp_dsack, tcp_timestamps커널 설정선택적 ACK(SACK, 중간에 빠진 부분 알림), 중복 수신 알림(DSACK), 왕복 시간 측정(타임스탬프)기본은 모두 켜짐. 2019년 SACK 보안 문제 때 꺼 둔 채 남은 서버가 있음. SACK이 꺼지면 RACK·TLP도 함께 동작하지 않음
net.ipv4.tcp_thin_linear_timeouts / TCP_THIN_LINEAR_TIMEOUTS커널 설정 / 소켓 옵션아직 ACK를 받지 못한 패킷(in-flight)이 4개 미만인 연결은 RTO를 처음 6번까지 두 배로 늘리지 않음기본은 꺼짐. 소켓 옵션으로 게임 연결에만 켤 수 있음. 첫 RTO를 줄이지는 않음
TCP_RTO_MAX_MS / net.ipv4.tcp_rto_max_ms소켓 옵션 / 커널 설정 (리눅스 6.15 이상)두 배씩 늘어나는 RTO의 상한(기본 120초)을 낮춤. 최소 1초연속 손실 뒤 RTO가 수십 초로 커지지 않게 함. 죽은 연결 판정도 함께 빨라짐
net.ipv4.tcp_mtu_probing커널 설정큰 패킷이 계속 사라지면 크기를 줄여 MTU 블랙홀을 통과기본 0(꺼짐). 1 = 재전송이 3초쯤 이어져 블랙홀이 의심될 때만 줄임(그동안은 멈춤). 2 = 처음부터 1,024바이트로 시작해 조금씩 키워 봄
ip route … rto_min경로 설정그 경로의 RTO 최소값(기본 200ms)을 낮춤서버끼리의 내부망에만. 인터넷 구간에 낮추면 불필요한 재전송이 늘어남. 리눅스 6.11 이상의 net.ipv4.tcp_rto_min_us는 서버 전체 값이라 인터넷 연결까지 함께 바뀜. 6.15 이상은 소켓 옵션 TCP_RTO_MIN_US로 내부 연결에만 낮출 수 있음
TCP_USER_TIMEOUT소켓 옵션재전송이 이어질 때 연결을 포기하기까지의 시간복구를 빠르게 하지는 않음. 죽은 연결을 빨리 끊고 재접속하게 함. 설정하지 않으면 리눅스는 재전송을 15번 안팎, 약 15분 이어간 뒤에야 끊음(tcp_retries2)
SO_KEEPALIVE + TCP_KEEPIDLE 등소켓 옵션유휴 연결이 살아 있는지 확인재전송과 별개. NAT·LB 매핑 유지와 죽은 연결 감지용
fq 큐 + SO_MAX_PACING_RATE, BBR큐 설정 / 소켓 옵션 / 커널 설정패킷을 고르게 나눠 보내 버스트(한꺼번에 몰아 보냄)로 인한 손실을 줄임손실을 “예방”하는 쪽. 복구 속도와는 별개

TCP 재전송의 근본 원인

무선 구간 손실 Wi-Fi / cellular link loss

와이파이와 모바일망은 무선 구간에서 몇 번 재전송하다가, 그래도 안 되면 패킷을 버립니다. 버려진 패킷은 TCP가 한참 뒤에 다시 보냅니다.

왜: 전파가 약하거나 간섭이 심해 무선 구간 전송이 연달아 실패 → 그러면: 무선 장비의 재시도 한도(보통 수~십여 번)를 넘으면 패킷을 버림 → 화면에서는: TCP 재전송 대기만큼 멈춤, 뒤 패킷은 수신 버퍼에서 대기하다 몰아치기

증상: 멈춤, 몰아치기, 순간이동 · 주 담당 외부·외부 · 함께 인프라팀·서버 인프라, 게임개발팀·서버 개발, 게임개발팀·클라이언트 개발

병목 대기열 넘침 (혼잡 손실) Tail drop at a congested bottleneck

공유기, 통신사 사이 연결 구간, 데이터센터 회선처럼 가장 좁은 곳의 대기열이 가득 차면 새로 오는 패킷을 버립니다.

왜: 영상·다운로드·다른 사용자 트래픽으로 병목 구간이 꽉 참 → 그러면: 대기열이 찬 동안 새로 도착하는 패킷이 연달아 버려짐(tail drop). 버려지지 않은 패킷도 꽉 찬 대기열 끝에서 기다림 → 화면에서는: 여러 패킷이 한꺼번에 사라져 긴 멈춤 뒤 몰아치기, 저녁 시간에 잦음

증상: 멈춤, 몰아치기, 고무줄 · 주 담당 인프라팀·네트워크 인프라 · 함께 외부·외부, 게임개발팀·클라이언트 개발

송신 버스트로 얕은 버퍼 넘침 Sender bursts overflow shallow buffers

서버가 틱마다 수천 명분 업데이트를 한순간에 몰아 보내면, 스위치의 작은 버퍼나 클라우드의 순간 한도가 1ms도 안 돼 넘쳐 일부가 버려집니다.

왜: 틱 시작 순간 모든 사람에게 보낼 패킷을 한꺼번에 전송 → 그러면: 여러 서버의 트래픽이 모이는 스위치 포트 버퍼(포트당 수백 KB~수 MB)나 클라우드 인스턴스 한도가 순간적으로 넘침(평균 사용률은 낮음) → 화면에서는: 여러 사람이 동시에 순간이동·멈칫, 평균 지표로는 원인이 안 보임

증상: 순간이동, 멈춤, 몰아치기 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라, 인프라팀·네트워크 인프라

폴리서의 초과분 폐기 Traffic policing

통신사 요금제, 클라우드 인스턴스 한도, DDoS 방어 장비는 정해진 속도를 넘는 패킷을 대기열에 넣지 않고 즉시 버리기도 합니다.

왜: 순간 전송량이 허용 속도·허용 버스트를 넘음 → 그러면: 넘는 패킷을 대기열 없이 바로 폐기(폴리싱) → 화면에서는: 버스트가 큰 순간마다 여러 개가 사라져 멈춤 뒤 몰아치기, 평균 속도는 한도 아래로 보임

증상: 멈춤, 몰아치기, 순간이동 · 주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라, 게임개발팀·서버 개발

물리 오류 (불량 선·광모듈·커넥터) Bit errors: bad cable, optics, dirty fiber

케이블 손상, 먼지 낀 광커넥터, 수명이 다한 광모듈은 비트 오류를 만들고 깨진 패킷은 장비가 조용히 버립니다.

왜: 선·광모듈·커넥터 불량으로 비트가 뒤집힘 → 그러면: 체크섬(CRC)이 맞지 않는 패킷을 장비가 폐기 → 화면에서는: 그 경로를 지나는 사람만 꾸준히 짧게 멈칫했다 몰아치기, 시간대와 상관없음

증상: 멈춤, 몰아치기, 순간이동 · 주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라, 외부·외부

듀플렉스 불일치 Duplex mismatch

한쪽은 자동 협상, 다른 쪽은 속도·듀플렉스를 고정해 두면 한쪽이 반이중으로 동작하며 부하가 걸릴 때마다 충돌로 패킷을 잃습니다.

왜: 장비 한쪽만 속도·듀플렉스를 고정 설정 → 그러면: 한쪽은 전이중, 다른 쪽은 반이중으로 동작해 충돌·늦은 충돌 발생 → 화면에서는: 평소엔 멀쩡하다가 트래픽이 늘면 그 장비를 지나는 사람 모두가 멈췄다 몰아치기

증상: 멈춤, 몰아치기 · 주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라

수신 서버 호스트의 패킷 폐기 Receiver host drops (ring, softirq, CPU)

패킷은 서버까지 왔는데 NIC의 링 버퍼(도착한 패킷을 잠시 담아 두는 버퍼)가 넘치거나, 커널의 수신 처리 코어가 포화되어 버려집니다.

왜: 접속자 폭증·코어 하나에 몰린 인터럽트·가상 머신 CPU 스틸·가상 스위치 과부하 → 그러면: 링 버퍼(rx_missed_errors 등, 이름은 드라이버마다 다름)나 커널 수신 대기열(softnet dropped)에서 폐기 → 화면에서는: 사람 몰릴 때 서버 전체에서 동시에 입력이 늦게 먹히고 멈칫

증상: 입력 지연, 멈춤, 몰아치기, 순간이동 · 주 담당 인프라팀·서버 인프라

방화벽·연결 추적의 폐기 Stateful firewall / conntrack drops

방화벽이나 리눅스 연결 추적(conntrack, 지나가는 연결을 테이블에 기록하는 기능)은 테이블이 가득 차거나, 연결 상태가 맞지 않는다고 판단하면 패킷을 버립니다.

왜: 연결 추적 테이블 가득(table full), 또는 오가는 경로가 달라 한쪽 방향만 방화벽을 지남(비대칭 경로) → 그러면: 방화벽이 “모르는 연결”이나 “윈도우 범위를 벗어난 시퀀스 번호”의 패킷으로 보고 폐기 → 화면에서는: 테이블이 차면 새 접속이 막히고 경로가 어긋나면 그 경로의 사람만 반복 재전송 끝에 접속 끊김

증상: 멈춤, 접속 끊김, 접속 불가·무한 로딩 · 주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라, 게임개발팀·서버 개발, 게임개발팀·클라이언트 개발

중간 장비 처리 한도 초과 (방화벽·IPS·DDoS 방어) Inline appliance PPS / CPU overload

방화벽, 침입 방지 장비(IPS), DDoS 방어 장비는 지나가는 패킷을 하나하나 검사합니다. 검사 능력을 넘는 순간부터 처리하지 못한 패킷을 버립니다.

왜: 피크 시간·이벤트에 작은 게임 패킷이 초당 수십만 개 넘게 몰림, 또는 검사 규칙이 무거움 → 그러면: 장비의 CPU·초당 패킷 수 한도가 차서 장비에서 폐기. 오탐이면 정상 패킷도 차단 → 화면에서는: 그 장비 뒤의 서버 전체에서 동시에 멈춤·순간이동, 사람 몰릴 때만 심해짐

증상: 멈춤, 몰아치기, 순간이동, 접속 끊김 · 주 담당 인프라팀·네트워크 인프라 · 함께 게임개발팀·서버 개발

MTU 블랙홀 (큰 패킷만 반복 손실) PMTU black hole

중간 구간이 받을 수 있는 크기가 작아졌는데 “너무 크다”는 알림(ICMP)이 막히면, 큰 패킷은 몇 번을 다시 보내도 계속 사라집니다.

왜: VPN·터널 구간에서 최대 크기가 줄고 크기 초과 알림은 방화벽에 막힘 → 그러면: 보내는 쪽은 이유를 모른 채 같은 큰 패킷을 계속 재전송, RTO는 두 배씩 증가 → 화면에서는: 평소엔 멀쩡하다가 인벤토리·사람 많은 곳·입장 로딩처럼 큰 데이터가 오가는 순간 뒤따르는 작은 패킷까지 전부 멈춤, 결국 접속 끊김이나 무한 로딩

증상: 멈춤, 접속 끊김, 접속 불가·무한 로딩 · 주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라, 게임개발팀·서버 개발

연결 도중 NAT·로드밸런서 매핑 만료 NAT / load balancer mapping expired mid-connection

유휴 연결의 매핑(이 연결을 어디로 전달할지 기록한 항목)을 중간 장비가 지우면, 다음에 보내는 패킷은 전달되지 못합니다. 재전송만 반복하다 접속이 끊기거나, 장비가 연결 거부(RST)를 돌려보내 곧바로 끊깁니다.

왜: 한동안 오가는 패킷이 없는 연결(자리 비움, 로비) → 그러면: 공유기 NAT·통신사 CGNAT·방화벽·로드밸런서·클라우드 보안 그룹이 유휴 매핑을 삭제 → 화면에서는: 다시 움직이는 순간 재전송이 이어지다 접속 끊김, 또는 바로 접속 끊김

증상: 접속 끊김, 멈춤 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발, 인프라팀·네트워크 인프라, 인프라팀·서버 인프라

경로 변경·ECMP 불량 경로 Route change / bad ECMP member

인터넷 경로가 바뀌는 몇 초 동안, 또는 여러 ECMP 경로 중 불량인 경로에 배정된 연결에서 패킷이 사라집니다.

왜: BGP 경로 재계산, 또는 여러 경로(ECMP·LAG) 중 한 경로의 장비·회선 불량 → 그러면: 경로 전환 중 일시 손실, 또는 그 경로를 타는 연결만 꾸준한 손실 → 화면에서는: 갑자기 몇 초 멈춘 뒤 몰아치기, 또는 “재접속하면 나아짐”(다른 경로로 배정)

증상: 멈춤, 몰아치기, 순간이동 · 주 담당 인프라팀·네트워크 인프라 · 함께 게임개발팀·서버 개발, 외부·외부

지연 급등으로 인한 불필요한 재전송 Spurious RTO from delay spikes

패킷은 사라지지 않고 잠깐 아주 늦게 도착했을 뿐인데, 그 지연이 RTO보다 길면 보내는 쪽이 손실로 판단해 재전송합니다.

왜: 버퍼블로트, 와이파이 절전, 모바일 무선 상태 전환, 가상 머신 일시 정지로 순간 지연이 수백 ms → 그러면: RTO가 먼저 만료되어 재전송, 원본도 곧 도착(받는 쪽은 중복으로 받음) → 화면에서는: 멈춤·몰아치기는 지연 급등 자체 때문. 불필요한 재전송은 멈춤을 거의 늘리지 않고 재전송 지표만 올려 손실로 오해받음

증상: 멈춤, 몰아치기, 입력 지연 · 주 담당 외부·외부 · 함께 인프라팀·서버 인프라, 게임개발팀·클라이언트 개발

순서 뒤바뀜으로 인한 불필요한 빠른 재전송 Reordering triggers spurious fast retransmit

여러 경로나 묶인 링크를 지나며 패킷 순서가 바뀌면, 받는 쪽이 중복 ACK로 “빠진 패킷 있음”을 알리고 보내는 쪽은 멀쩡한 패킷을 다시 보냅니다.

왜: 패킷 단위로 경로를 나누는 장비, 패킷 단위로 나눠 싣는 LAG(링크 묶음), 경로가 바뀌는 순간이 순서를 뒤섞음 → 그러면: 뒤 패킷이 먼저 도착해 중복 ACK 3개가 쌓임 → 빠른 재전송 → 화면에서는: 드문드문 오가는 게임 패킷은 거의 영향 없음. 사람 많은 곳의 큰 업데이트와 패치 다운로드가 느려지고 가끔 뚝뚝 끊김

증상: 뚝뚝 끊김, 입력 지연 · 주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라

ACK가 늦거나 사라짐 (업로드 포화) ACK path congestion on asymmetric links

데이터는 잘 도착했는데 “받았다”는 ACK가 꽉 찬 업로드 대기열에서 늦어지거나 사라지면, 보내는 쪽이 손실로 판단해 재전송합니다.

왜: 집에서 영상 업로드·클라우드 백업으로 업로드가 꽉 참 → 그러면: ACK가 공유기 대기열에서 수백 ms 늦어지거나 넘쳐서 버려짐 → 화면에서는: 서버가 보내는 게임 패킷은 대체로 제때 옴. 같은 업로드 대기열에 쌓인 내 입력이 늦어 입력 지연·고무줄, 가끔 불필요한 재전송

증상: 입력 지연, 고무줄 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

RTO 설정이 환경과 맞지 않음 RTO min too low or too high

RTO 최소값을 너무 낮추면 조금만 늦어도 불필요한 재전송이 나고 기본값(200ms)은 게임 입장에서 너무 길어 한 번 잃을 때마다 오래 멈춥니다.

왜: 데이터센터용으로 RTO 최소값을 크게 낮춤, 또는 인터넷 구간에 기본값 그대로 사용 → 그러면: 낮으면 순간 지연에도 재전송 폭주, 높으면 손실마다 긴 대기 → 화면에서는: 기본값이면 손실 한 번에 수백 ms 멈춤 뒤 몰아치기, 너무 낮추면 멈춤은 줄지만 불필요한 재전송이 급증해 회선을 낭비

증상: 멈춤, 몰아치기, 입력 지연 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발

thin stream의 느린 복구 Thin streams fall back to RTO

게임처럼 작은 패킷을 드문드문 보내면 “뒤따르는 패킷 3개”가 모이기 전에 RTO가 먼저 옵니다. 대용량 전송보다 같은 손실에 훨씬 오래 멈춥니다.

왜: 패킷 간격이 100ms 안팎이라 아직 ACK를 받지 못한(in-flight) 패킷이 몇 개 없음 → 그러면: 중복 ACK 3개가 모이려면 300ms 넘게 걸려 RTO(핑 + 200ms)가 먼저 발동, 연속 손실이면 두 배씩 → 화면에서는: 손실 한 번에 0.3초 안팎 멈춤, 다시 보낸 것까지 잃으면 1초 가까이 멈춘 뒤 몰아치기

증상: 멈춤, 몰아치기 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라, 게임개발팀·클라이언트 개발

중간 장비의 TCP 옵션 제거 Middlebox strips TCP options

일부 방화벽·가속 장비가 TCP 옵션을 지우거나 고치면, 여러 개를 잃었을 때 한 왕복에 하나씩만 복구하거나 윈도우(한 번에 보낼 수 있는 양)가 작아져 느려집니다.

왜: 방화벽의 “TCP 정규화”, 오래된 가속 장비가 SACK·타임스탬프·윈도우 스케일 옵션을 제거 → 그러면: 잃은 패킷이 여러 개면 왕복마다 하나씩 복구, 윈도우가 64KB로 제한됨 → 화면에서는: 손실마다 멈춤이 훨씬 길어지고(SACK이 없으면 RACK-TLP도 못 씀) 풀리면 몰아치기. 패치 같은 대용량 전송도 느림

증상: 멈춤, 몰아치기 · 주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라

제로 윈도우 (재전송처럼 보이는 멈춤) Zero window, often mistaken for retransmission

받는 쪽 프로그램이 소켓을 제때 읽지 않아 버퍼가 가득 차면, 보내는 쪽은 전송을 멈추고 제로 윈도우 프로브만 보냅니다. 회선 문제가 아닙니다.

왜: 클라이언트 프레임 멈춤, 서버 스레드 막힘으로 소켓을 못 읽음 → 그러면: 수신 윈도우가 0이 되어 보내는 쪽이 전송을 멈추고 프로브만 보냄(간격이 점점 늘어남) → 화면에서는: 멈춤 뒤 몰아치기. 패킷 캡처에 “ZeroWindow”가 보이고 손실은 없음

증상: 멈춤, 몰아치기 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발, 인프라팀·서버 인프라

접속 요청(SYN) 재전송 SYN retransmission on connect

접속 요청이 접속 대기열(backlog) 넘침이나 방화벽 차단으로 사라지면, 클라이언트 OS가 1초 뒤부터 간격을 늘려 가며 다시 보냅니다.

왜: 점검 직후 접속 폭주로 서버 접속 대기열이 넘치거나, 방화벽·DDoS 방어가 SYN을 버림 → 그러면: 클라이언트 OS가 1초 뒤부터 정해진 간격으로 SYN 재전송(예전 리눅스는 1초 → 2초 → 4초) → 화면에서는: 접속 버튼 뒤 1초, 3초처럼 초 단위로 딱 떨어지게 늦고 계속 실패하면 접속 불가·무한 로딩

증상: 접속 불가·무한 로딩 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라, 인프라팀·네트워크 인프라, 게임개발팀·클라이언트 개발

07담당 구분

게임개발팀과 인프라팀의 담당

같은 렉이라도 고치는 곳이 다릅니다. 클라이언트·서버 코드와 동기화 설계는 게임개발팀이, 회선·네트워크 장비·서버 장비·DB 장비는 인프라팀이 맡습니다. 유저의 PC와 집 네트워크, 통신사 구간, 클라우드 사업자 쪽 문제는 두 팀 모두 직접 고칠 수 없어 안내하거나 요청하거나 우회합니다. 모든 원인 카드에 주 담당과 함께 대응할 곳을 표시했고 카드의 “수치 감각·확인 방법·팀별 대응”을 펼치면 팀마다 할 일이 나뉘어 있습니다.

  1. 제보·경보증상, 초 단위 시각, 서버·채널
  2. 누가 겪나한 명·한 집 / 특정 통신사·지역 / 특정 서버·채널 / 전체
  3. 먼저 부를 곳후보 원인 카드의 주 담당. 진단 도우미의 “먼저 확인할 곳”
  4. 넘길 정보IP·통신사, 끊김 사유, 관련 그래프, 직전 변경
  5. 함께 할 일카드의 팀별 할 일로 나눠 맡기
티켓이 들어와서 팀별 할 일로 나뉠 때까지의 흐름입니다. “누가 겪나”가 담당을 가장 크게 가르고 자세한 기준은 아래 표와 관측으로 판정하기에 있습니다.
담당맡는 범위주로 쓰는 해결 수단
게임개발팀클라이언트게임 클라이언트 코드: 프레임·GC·로딩, 보간·외삽·예측, 클라이언트의 네트워크 처리(하트비트 보내기·자동 재접속 포함)코드 수정, 보간 버퍼·예측 조정, 로딩 방식 변경, 하트비트 간격·재접속 흐름, 클라이언트 패치
게임개발팀서버게임 서버 코드: 틱·스레드·락, 동기화 설계, 접속 처리(accept 루프·listen 인자), 하트비트 응답·끊긴 연결 정리, 소켓 옵션, 쿼리·트랜잭션 설계로직 최적화, 비동기 호출, 틱·지역 분산, 로그인 대기열, 세션 토큰으로 이어 받기, 소켓 옵션(TCP_NODELAY 등), 쿼리·인덱스 설계, 서버 패치
인프라팀네트워크회선과 IDC 네트워크 장비(스위치·라우터·방화벽·로드밸런서·DDoS 방어), 클라우드 네트워크 ACL·VPC 라우팅·로드밸런서, 통신사·피어링장비 설정·교체, 회선·피어링 증설, 경로 변경, 통신사 에스컬레이션, 로드밸런서·방화벽의 유휴 타임아웃·세션 한도 조정
인프라팀서버 장비·OS서버 장비·클라우드 인스턴스(보안 그룹·연결 추적 포함), OS·커널 설정, NIC, 배포·모니터링 환경증설·인스턴스 변경, 커널 설정(sysctl: somaxconn·conntrack 등), 보안 그룹 구성·연결 추적 시간, NIC 링 버퍼·인터럽트 분산, 크론·백업 시간 조정
인프라팀DB 장비DB 서버·스토리지, DB 설정·복제·백업, 캐시 서버DB 증설, 스토리지 IOPS 확보, DB 파라미터·복제 설정, 백업·체크포인트 조정
외부유저·통신사·클라우드유저 PC·집 네트워크, 통신사 구간(우리 계약 밖), 클라우드 사업자유저 안내(유선 연결 등), 통신사·클라우드 사업자에 요청, 게임 쪽 우회·완화

층·주제별 담당 한눈에 보기

굵은 숫자는 그 담당이 주 담당인 원인 수, +숫자는 함께 대응하는 원인 수입니다. 칸을 누르면 아래에 그 원인과 팀의 할 일이 나옵니다.

경계가 애매할 때: 원인이 있는 팀이 주 담당, 다른 팀은 완화와 확인

주 담당은 근본 원인이 있는 곳, 또는 그 원인을 없앨 수 있는 곳입니다. 회선이나 장비가 원인이어도 게임개발팀은 그동안 영향을 줄이는 설계(보간 버퍼, 입력 중복 전송, 재접속)로 버티고 서버 코드가 원인이면 인프라팀이 장비를 늘려도 잠시 미룰 뿐입니다. 자주 헷갈리는 경계는 이렇게 정했습니다.

  • 가만히 있다 끊김: 유저 공유기와 통신사 장비의 유휴 타임아웃은 우리가 바꿀 수 없고 그 매핑은 안에서 나가는 패킷으로만 확실히 유지됩니다. 그래서 클라이언트가 하트비트를 보내고 끊기면 자동 재접속하며 서버는 하트비트에 응답하고 못 받으면 연결을 먼저 정리한 뒤 세션 토큰으로 이어 받습니다. 인프라팀은 우리 장비의 타임아웃 값을 알려 주고 필요하면 늘립니다.
  • 접속 대기열(backlog) 넘침: 실제 한계는 서버 코드의 listen 인자와 accept 루프라서 서버 개발이 주 담당이고 서버 장비·OS는 커널 상한(somaxconn)과 SYN 쿠키를 맡습니다.
  • 클라우드: 보안 그룹과 인스턴스의 연결 추적은 서버 장비·OS, 네트워크 ACL·VPC 라우팅·클라우드 로드밸런서는 네트워크가 맡습니다.

표의 “먼저”는 그 현상에 해당하는 원인 카드들의 주 담당을 세어 정한, 처음 부를 곳입니다. 두 곳이면 앞쪽이 주 담당인 카드가 가장 많은 곳이고 뒤쪽은 처음부터 함께 부를 곳입니다.

현상게임개발팀이 할 일인프라팀이 할 일먼저 볼 지표
특정 통신사·지역에서 손실·지터가 큼
먼저인프라팀네트워크
적응형 보간 버퍼, 입력 겹쳐 보내기, 손실에 강한 UDP 전송, 연결별 손실·재전송 통계로 겪는 사람의 IP·포트·시각 뽑기, 이동 검증 기준을 회선 상태만큼 완화게임과 같은 프로토콜·포트로 양방향 경로 측정(mtr), 불량 경로 빼기, 통신사 에스컬레이션, 피어링·회선 추가통신사별 손실률·지터 분포, 재전송률
TCP 재전송 증가
먼저인프라팀네트워크게임개발팀서버
TCP_NODELAY, 한 틱의 전송을 틱 안에 나눠 보내기, 소켓을 제때 읽기(제로 윈도우 막기), 하트비트로 매핑 유지, 실시간 패킷은 UDP나 다른 연결로, 보내기 버퍼에 옛 위치 쌓지 않기(TCP_NOTSENT_LOWAT)손실 지점 제거(케이블·광모듈·듀플렉스·폴리서·방화벽 연결 추적·MTU), MSS 조정, 서버 링 버퍼·인터럽트 분산, 커널 복구 설정(RACK·tcp_mtu_probing)재전송 증가분(nstat), 제로 윈도우 횟수, NIC·스위치 포트의 드롭·CRC 카운터
서버 CPU 포화로 틱 초과
먼저게임개발팀서버
시야 계산·브로드캐스트 최적화, 틱을 여러 스레드로 나누기, 붐비는 지역·채널 나누기, 워커 스레드 수를 CPU 한도에 맞추기, 틱 처리 시간을 지표로 남기기단일 코어 성능(클럭)이 높은 CPU·인스턴스, 코어별 CPU 사용률 경보, CPU 스틸·컨테이너 CPU 스로틀링 확인, 인터럽트 처리 코어와 틱 스레드 코어 분리틱 처리 시간, 코어별 CPU 사용률·steal·스로틀링 횟수(nr_throttled)
DB 응답 지연
먼저게임개발팀서버인프라팀DB 장비
쿼리·인덱스·트랜잭션 설계(짧게, 잠금 순서 통일), 게임 스레드 밖에서 비동기 호출, 묶어서 조회·캐시, 커넥션 풀 크기·대기 타임아웃 조정느린 쿼리·실행 계획·락 대기를 찾아 게임팀에 공유, 체크포인트·복제·통계 갱신 설정, 스토리지 IOPS, 서버 수 × 풀 크기가 최대 연결 수 안인지 확인, DB 장비 증설느린 쿼리 로그, 락 대기, 커넥션 대기, 복제 지연, IOPS
점검 직후 접속 불가
먼저게임개발팀서버
접속을 받는 스레드(accept 루프)가 다른 일로 멈추지 않게, listen의 backlog 인자 늘리기, 로그인 대기열 시스템, 로그인 쿼리 묶기(N+1 없애기), 클라이언트 재시도 간격을 늘리며 무작위로 분산커널 somaxconn·SYN 쿠키, 방화벽·로드밸런서 세션 한도, 서버 conntrack·파일 디스크립터 한도, DB 캐시 예열, 이벤트 전 서버 미리 확장ListenOverflows, 세션 테이블·conntrack 사용률, 로그인 쿼리 수·커넥션 대기
가만히 있으면 접속 끊김
먼저게임개발팀클라이언트
클라이언트: 가장 짧은 유휴 타임아웃의 절반 이하 간격으로 하트비트 보내기(하나가 늦거나 빠져도 타임아웃 전에 다음 것이 닿도록), 끊기면 자동 재접속. 서버: 하트비트에 응답하고 일정 시간 못 받으면 연결을 먼저 정리, 세션 토큰으로 이어 받기.경로에 있는 로드밸런서·방화벽의 유휴 타임아웃(네트워크)과 클라우드 보안 그룹의 연결 추적 시간(서버 장비·OS)을 모아 게임팀에 공유, 우리 장비는 필요하면 늘리기. 유저 공유기·통신사 CGNAT의 타임아웃은 바꿀 수 없음끊긴 연결의 유휴 시간 분포(한 값 근처에 몰리면 그 타임아웃이 설정된 장비), 망 종류(모바일·유선)
정해진 시각마다 서버 멈춤
먼저게임개발팀서버인프라팀서버 장비·OS
정각 이벤트·저장·타이머·캐시 만료 시각을 무작위로 분산, 배치 쿼리는 잘게 나눠 조금씩, 멈춤이 짧은 GC를 직접 지정크론·백업·로그 압축 시각 분산과 I/O 우선순위 낮추기, DB 백업은 복제본에서 하고 체크포인트는 고르게, 디스크 버스트 크레딧 확인, 백업 전송 속도 제한멈춘 시각과 작업 스케줄(크론·백업·배치·체크포인트), GC 로그
DDoS·트래픽 폭주
먼저인프라팀네트워크
게임 트래픽 패턴(포트, 패킷 크기, 초당 패킷 수)을 인프라팀에 공유, 계정·캐릭터별 요청 빈도 제한, 비정상 패킷 조기 차단DDoS 방어(스크러빙)와 게임 트래픽에 맞춘 방어 규칙, 서버 주소 숨기기, 장비의 초당 패킷 한도, IP 기준 제한은 통신사 공유 IP·PC방을 고려초당 패킷 수, 장비 CPU·드롭, 지역·통신사별 접속 실패율(오탐 확인)
유저 와이파이·PC 문제
먼저외부유저·통신사·클라우드게임개발팀클라이언트
게임 안 네트워크 상태 표시(핑·손실), 지터에 따라 보간 버퍼 길이 자동 조절, 렉이 생긴 때의 로그에 망 종류·PC CPU 사용률 남기기, 유선 연결 등 안내 문구직접 고칠 수 없음. 같은 통신사·지역에 제보가 몰리면 회선 문제로 다시 분류제보의 회선·기기 정보, 같은 통신사·지역 비율

넘길 때 챙길 정보

게임개발팀 → 인프라팀

  • 정확한 시각(초 단위, 시간대 표기)과 지속 시간, 지금도 계속되는지
  • 서버·채널 ID, 영향 범위(나만·특정 통신사·서버 전체)와 영향받은 인원(동접 대비)
  • 증상 이름과 모양: 끊김이면 끊기기 전 유휴 시간, 멈춤이면 길이와 반복 주기
  • 겪는 사람의 IP·포트·통신사·지역(여러 경로 중 하나가 불량이면 포트까지 있어야 가려짐), 게임이 쓰는 프로토콜(TCP·UDP)과 서버 포트
  • 게임 쪽 지표: 틱 처리 시간, 핑·손실 분포, 재전송이 늘어난 연결 수, 끊김 사유(하트비트 시간 초과, 연결 거부(RST) 등)
  • 지금 쓰는 하트비트 간격, 서버의 무응답 판정 시간, 재시도 방식
  • 최근 배포·설정 변경 여부, 이미 확인해 제외한 원인

인프라팀 → 게임개발팀

  • 같은 시각의 장비·회선 지표(사용률, 드롭·에러 카운터, 세션 수)와 서버 OS 지표(ListenOverflows, conntrack 사용률, CPU steal)
  • 경로에 있는 장비의 타임아웃·한도 값: 로드밸런서·방화벽 유휴 타임아웃, 보안 그룹 연결 추적 시간, 세션 수·초당 패킷 수 한도
  • 장비·회선 변경 이력과 예정된 작업(교체, 설정 변경, 백업·크론, 통신사 작업 공지)
  • 통신사·클라우드 사업자에 낸 문의 번호와 답을 받을 예상 시각
  • 임시 조치(우회, 한도 완화)와 되돌릴 시점
  • 원인 구간과 결론, 재발 방지 계획
  • 게임 쪽에 필요한 조치(하트비트 간격, 재시도 방식, 연결 수 제한 등)

두 팀 공통: 장애 대응 책임자 한 명을 정해 한 채널에 시간순 기록을 남기고 다음 공유 시각을 미리 알립니다. 주 담당이 다른 팀으로 바뀌면 이 기록을 함께 넘겨 같은 확인을 되풀이하지 않게 합니다. 끝나면 같은 기록으로 해당 원인 카드의 담당과 할 일을 고칩니다.

클라이언트 게임 프로세스

플레이어 PC나 폰에서 돌아가는 게임 프로그램 그 자체입니다. 네트워크에 문제가 없어도 여기서 프레임이 늦으면 화면이 뚝뚝 끊깁니다. 네트워크가 나쁠 때 그걸 얼마나 잘 가려 주느냐도 여기서 결정됩니다.

게임은 1초에 60번쯤 같은 일을 반복합니다. 입력을 읽고 받은 패킷을 처리하고 게임 상태를 한 단계 갱신하고 화면을 그립니다. 이 루프 한 번이 프레임이고 60FPS라면 한 프레임에 16.7ms가 주어집니다(30FPS로 도는 폰 게임은 33.3ms). 한 프레임이 늦어지면 그만큼 화면이 멈췄다가, 다음 프레임에서 밀린 만큼 한 번에 움직입니다.

네트워크 쪽에서 클라이언트가 하는 일은 “모자란 정보 메우기”입니다. 다른 플레이어의 위치는 서버에서 띄엄띄엄 오기 때문에 그 사이를 이어 그려야 하고(보간), 패킷이 끊기면 추측해서 움직여야 하며(외삽), 내 캐릭터는 서버 확인을 기다리지 않고 먼저 움직여 보여 줍니다(예측). 이 기술들이 실패하는 방식이 곧 순간이동, 고무줄, 뚝뚝 끊김입니다.

비유

게임 클라이언트는 생중계 화면을 만드는 방송국 부조정실입니다. 현장(서버)에서 사진이 띄엄띄엄 오면 그 사이를 자연스럽게 이어 붙여 영상처럼 보여 줍니다. 사진이 늦게 오면 이어 붙일 사진이 없어 화면이 멈추고 편집실 자체가 바빠도 방송이 끊깁니다.

이 층에서 렉을 만드는 원인

프레임 타임 스파이크 Frame hitch

한 프레임 계산이 평소보다 몇 배 오래 걸려 화면이 잠깐 멈춥니다.

왜: 스킬 이펙트 폭증, 대량 스폰, UI 전체 갱신이 한 프레임에 몰림 → 그러면: 16.7ms 안에 못 끝내고 50~300ms가 걸림 → 화면에서는: 화면이 멈칫했다가 다음 프레임에 모두가 한 번에 이동

증상: 뚝뚝 끊김, 멈춤 · 주 담당 게임개발팀·클라이언트 개발

클라이언트 가비지 컬렉션 Client GC (Unity C#, Unreal, Lua)

쓰고 버린 메모리(가비지)를 회수하는 동안 게임 전체가 멈춥니다. 규칙적인 간격으로 뚝뚝 끊기는 것이 특징입니다.

왜: 매 프레임 임시 문자열·배열·리스트를 만들고 버림 → 그러면: 가비지가 쌓이면 GC가 메인 스레드를 멈추고 회수 → 화면에서는: 몇 초~몇십 초마다 규칙적으로 뚝뚝 끊김

증상: 뚝뚝 끊김, 멈춤 · 주 담당 게임개발팀·클라이언트 개발

메인 스레드 동기 로딩·셰이더 컴파일 Synchronous asset load, shader compile

처음 보는 지역·몬스터·이펙트를 그리기 직전에 파일을 읽고 셰이더를 만드느라 멈춥니다.

왜: 새 지역 진입, 처음 보는 스킬·장비·몬스터 등장 → 그러면: 메인 스레드가 파일 읽기와 셰이더 컴파일을 기다림 → 화면에서는: 처음 한 번만 0.1~1초 멈춤, 두 번째부터는 괜찮음

증상: 멈춤, 뚝뚝 끊김 · 주 담당 게임개발팀·클라이언트 개발

저장장치가 느려 에셋 스트리밍이 밀림 Slow storage stalls asset streaming

HDD처럼 느린 저장장치에서는 오픈월드의 텍스처·모델을 읽는 속도가 이동을 따라가지 못해, 개체가 늦게 뜨거나 게임이 읽기를 기다리며 끊깁니다.

왜: 탈것·텔레포트로 빠르게 이동하거나 사람 많은 곳에 들어가 새 텍스처·모델이 한꺼번에 필요해짐 → 그러면: HDD 같은 느린 저장장치가 필요한 속도로 읽지 못해 읽기 요청이 쌓이고 일부 로딩은 메인 스레드가 끝날 때까지 기다림 → 화면에서는: 텍스처가 한동안 흐릿하고 건물·캐릭터가 늦게 나타나며 읽기를 기다리는 순간 뚝뚝 끊김·멈춤

증상: 안 보임·유령 개체, 뚝뚝 끊김, 멈춤 · 주 담당 게임개발팀·클라이언트 개발 · 함께 외부·외부

대규모 인원 렌더링 부하 Render/animation cost of crowds

공성전·월드 보스처럼 수백 명이 한 화면에 들어오면 그리는 비용 자체가 감당이 안 됩니다.

왜: 한 화면에 수백 명과 이펙트가 겹침 → 그러면: 애니메이션·그림자·이름표·이펙트 비용이 인원에 비례해 증가 → 화면에서는: FPS가 60 → 15로 떨어져 모든 움직임이 뚝뚝 끊기고 입력도 늦음

증상: 뚝뚝 끊김, 입력 지연 · 주 담당 게임개발팀·클라이언트 개발

메인 스레드 패킷 처리 병목 Network processing on the main thread

받은 패킷을 프레임마다 정해진 만큼만 처리하면, 몰려온 패킷이 다음 프레임으로 계속 밀립니다.

왜: 사람 많은 곳에서 초당 수천 개의 업데이트가 도착 → 그러면: 메인 스레드가 프레임당 처리량 제한에 걸려 다 못 읽음 → 화면에서는: 다른 사람 움직임이 점점 늦게, 몰아서 반영

증상: 몰아치기, 입력 지연 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

보간 버퍼가 없거나 짧음 Missing/short interpolation buffer

서버 패킷을 받자마자 그리면 지터(도착 간격의 흔들림)가 그대로 화면에 드러납니다.

왜: 받은 위치를 바로 그리거나 버퍼가 지터보다 짧음 → 그러면: 늦게 온 패킷만큼 멈추고 몰려온 패킷만큼 튐 → 화면에서는: 다른 캐릭터가 멈칫멈칫 움직임

증상: 뚝뚝 끊김 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

과도한 외삽(데드 레커닝) Over-extrapolation / dead reckoning

패킷이 오지 않는 동안 마지막 속도로 계속 움직여 보여 주다가, 틀린 걸 알고 되돌립니다.

왜: 패킷 수신이 끊겨 마지막 방향·속도로 계속 이동시킴 → 그러면: 실제로는 상대가 멈추거나 방향을 바꿨음 → 화면에서는: 상대 캐릭터가 한참 가다가 진짜 위치로 휙 옮겨지거나 벽을 뚫고 지나감. 패킷 도착 간격이 들쭉날쭉하면 앞서 나갔다 당겨지기를 반복해 떨리듯 움직임

증상: 순간이동, 뚝뚝 끊김 · 주 담당 게임개발팀·클라이언트 개발

클라이언트 예측 불일치 Prediction mismatch / reconciliation

내 클라이언트가 먼저 움직여 보여 줬는데 서버가 다르게 계산하면 내 캐릭터가 끌려갑니다.

왜: 클라이언트가 서버 확인 전에 먼저 움직임(예측) → 그러면: 서버는 충돌·이동 속도·버프를 다르게 계산하거나 명령을 못 받음 → 화면에서는: 확인이 올 때 내 캐릭터가 뒤로 끌려감

증상: 고무줄 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

고정 타임스텝 따라잡기 폭주 Fixed-timestep catch-up / spiral of death

한 번 멈춘 뒤 밀린 계산을 몰아서 하다가, 그 계산 때문에 또 밀립니다.

왜: 게임 시뮬레이션을 고정 간격으로 돌리는데 한 번 멈춤 → 그러면: 밀린 스텝을 한 프레임에 몰아서 계산 → 화면에서는: 긴 프레임이 줄줄이 이어지며 튀거나, 상한에 걸려 세계가 느려짐

증상: 뚝뚝 끊김, 몰아치기, 슬로우모션 · 주 담당 게임개발팀·클라이언트 개발

시계 동기화 오차 Clock sync error

클라이언트가 추정한 서버 시각이 틀리면 보간 시점과 쿨타임 판정이 어긋납니다.

왜: 접속할 때 한 번만 서버 시간을 맞추고 핑이 변해도 그대로 둠 → 그러면: 보간할 시점·쿨타임 끝나는 시각이 서버와 어긋남 → 화면에서는: 상대가 가끔 멈칫, 쿨타임이 끝났는데 스킬이 거절됨

증상: 뚝뚝 끊김, 씹힘·롤백 · 주 담당 게임개발팀·클라이언트 개발

float 시간 정밀도 손실 Float time precision loss on long sessions

게임 시각을 정밀도가 낮은 소수 형식(float)으로 들고 있으면, 켜 둔 시간이 길수록 시간 해상도(구별할 수 있는 가장 작은 시간 차이)가 떨어져 움직임과 이펙트가 떨립니다.

왜: 게임을 켠 뒤 흐른 시간을 float로 쌓거나 그대로 셰이더에 넘김 → 그러면: 켜 둔 시간이 길수록 float가 나타낼 수 있는 가장 작은 차이가 커짐 → 화면에서는: 며칠 켜 둔 클라이언트만 캐릭터·애니메이션·흐르는 이펙트가 덜덜 떨리고 다시 켜면 멀쩡함

증상: 뚝뚝 끊김 · 주 담당 게임개발팀·클라이언트 개발

V-Sync와 렌더 대기열 V-Sync, render queue

GPU가 그린 프레임을 몇 장 대기열에 쌓아 두었다가 모니터 주기에 맞춰 내보내는 동안 입력이 늦어집니다.

왜: 그래픽 드라이버가 프레임을 1~3장 미리 대기열에 쌓음 → 그러면: 입력이 화면에 반영되기까지 그만큼 더 걸림 → 화면에서는: 핑은 낮은데 조작이 묵직하고 굼뜸

증상: 입력 지연, 뚝뚝 끊김 · 주 담당 게임개발팀·클라이언트 개발 · 함께 외부·외부

클라이언트 메모리 누수 Client memory leak

오래 켜 둘수록 메모리가 늘어 점점 느려지다가 결국 게임이 강제로 꺼집니다.

왜: 지역을 오갈 때 텍스처·UI·이펙트가 해제되지 않음 → 그러면: GC가 잦아지고 OS 메모리가 부족해 스왑 발생 → 화면에서는: 몇 시간 플레이 뒤 점점 뚝뚝 끊기다가 강제 종료(플레이어에게는 접속 끊김처럼 보임)

증상: 뚝뚝 끊김, 접속 끊김 · 주 담당 게임개발팀·클라이언트 개발

클라이언트 크래시 Client crash

처리하지 못한 오류로 게임이 꺼집니다. 플레이어에게는 접속 끊김처럼 보이지만 서버는 정상입니다.

왜: 널 참조, 메모리 부족, 그래픽 드라이버 오류 → 그러면: 게임 프로세스가 강제 종료 → 화면에서는: “튕겼다”는 제보. 같은 시각 다른 사람은 멀쩡

증상: 접속 끊김 · 주 담당 게임개발팀·클라이언트 개발 · 함께 외부·외부

게임 보안 모듈(안티치트) 검사 Anti-cheat scan and heartbeat

해킹을 막으려고 게임과 함께 도는 보안 모듈이 주기적으로 검사합니다. 검사가 무겁거나 보안 서버와 주고받는 하트비트(주기적인 생존 확인 신호)가 늦으면 뚝뚝 끊기거나 접속이 끊깁니다.

왜: 보안 모듈이 주기적으로 게임 메모리·실행 중인 프로그램·드라이버를 검사 → 그러면: 검사하는 동안 게임 스레드가 멈추거나, 하트비트가 제때 못 감 → 화면에서는: 일정한 간격으로 멈칫, 심하면 보안 오류 안내와 함께 접속 끊김

증상: 뚝뚝 끊김, 멈춤, 접속 끊김 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

클라이언트 OS와 기기

게임은 윈도우, 안드로이드, iOS 위에서 다른 프로그램들과 CPU·메모리·네트워크를 나눠 씁니다. 운영체제가 게임에 CPU를 늦게 배정하거나, 배터리를 아끼려고 속도를 줄이거나, 백그라운드 앱을 일시 정지시키면 렉이 됩니다.

운영체제(OS)의 스케줄러(CPU를 쓸 차례를 정하는 기능)가 여러 프로그램에 CPU 시간을 나눠 줍니다. 게임, 백신, 브라우저, 업데이트 프로그램이 모두 “내 차례”를 기다리며 OS는 몇 ms에서 수십 ms씩(타임 슬라이스) 번갈아 코어를 배정합니다. OS가 앞에 띄운 게임(포그라운드)에 우선순위를 조금 더 주긴 하지만 코어보다 할 일이 많으면 게임도 대기해야 하고 그 기다림이 프레임을 늦춥니다.

네트워크도 OS를 거칩니다. 랜카드·와이파이 칩이 받은 패킷은 드라이버와 OS의 수신 버퍼에 담겼다가 게임이 꺼내 갈 때까지 기다립니다. 게임이 바빠서 늦게 꺼내면 버퍼가 넘치고 한꺼번에 꺼내면 몰아치기가 됩니다. 모바일에서는 OS가 배터리를 아끼려고 무선 연결을 절전 상태로 돌리고 앱 자체도 수시로 일시 정지시킵니다.

비유

OS는 한 대뿐인 주방을 여러 요리사가 나눠 쓰게 하는 주방장입니다. 게임이 급한 요리를 하고 있어도, 백신 검사라는 요리사가 화구를 차지하면 기다려야 합니다. 주방이 너무 뜨거워지면(발열) 불 세기도 줄여 버립니다.

이 층에서 렉을 만드는 원인

백그라운드 프로세스의 CPU 점유 Background CPU contention

백신 검사, 윈도우 업데이트, 방송 프로그램, 브라우저 영상이 코어를 차지하면 게임 스레드가 CPU를 배정받지 못하고 기다립니다.

왜: 다른 프로그램이 CPU 코어를 오래 차지 → 그러면: 게임 스레드가 스케줄링 대기 → 화면에서는: 프레임이 늦고 받은 패킷 처리도 늦어짐

증상: 뚝뚝 끊김, 몰아치기 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

절전 모드·발열 스로틀링 Power saving, thermal throttling

노트북 배터리 모드, 폰 절전 모드, 기기 발열 때문에 CPU·GPU 속도가 떨어집니다. 발열은 처음엔 괜찮다가 한참 뒤부터 느려지는 게 특징입니다.

왜: 배터리·절전 모드이거나 기기가 뜨거워짐 → 그러면: CPU·GPU 클럭을 기기에 따라 30~50% 낮춤 → 화면에서는: 절전 모드는 켜자마자, 발열은 몇 분~20분쯤 플레이한 뒤부터 FPS가 떨어지고 뚝뚝 끊김

증상: 뚝뚝 끊김, 입력 지연 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

타이머 해상도 Timer resolution (Windows 15.6ms)

윈도우의 기본 타이머는 15.6ms 단위라 “1ms만 쉬기”가 실제로는 다음 타이머 주기까지, 길게는 15.6ms로 늘어납니다.

왜: 프레임 제한·패킷 전송을 Sleep(잠깐 대기) 방식으로 구현 → 그러면: OS가 15.6ms 단위로만 깨워 줌 → 화면에서는: 프레임 간격과 입력 전송 간격이 들쭉날쭉

증상: 뚝뚝 끊김 · 주 담당 게임개발팀·클라이언트 개발

모바일 앱 백그라운드 전환 App suspended in background

알림을 보려고 앱을 잠깐 내리면 OS가 몇 초 뒤 앱을 일시 정지(suspend)하고, 그동안 서버는 나를 끊습니다.

왜: 메시지 확인·전화로 게임을 내림 → 그러면: 게임 엔진이 게임 진행을 멈추고 OS도 곧 앱과 네트워크를 정지시킴 → 화면에서는: 돌아오면 이미 접속 끊김, 재접속

증상: 접속 끊김 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

와이파이 ↔ LTE·5G 전환 Network switch changes IP

집 밖으로 나가며 와이파이가 끊기고 LTE·5G로 바뀌면 내 IP 주소가 바뀌어 기존 연결이 무효가 됩니다.

왜: 와이파이 신호가 약해져 모바일망으로 전환 → 그러면: 내 IP 주소가 바뀌어 옛 주소로 맺은 연결로는 더 주고받을 수 없음 → 화면에서는: 잠깐 멈춘 뒤 접속 끊김 또는 재접속

증상: 멈춤, 접속 끊김 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발, 인프라팀·네트워크 인프라

보안 프로그램의 패킷 검사 Antivirus / firewall inspection

백신·방화벽이 모든 패킷을 검사하면 지연이 늘고 과하면 게임을 공격으로 오인해 막습니다.

왜: 보안 프로그램이 송수신 패킷을 하나하나 검사 → 그러면: 패킷마다 지연이 붙고 검사가 밀리면 버려짐 → 화면에서는: 핑이 불규칙하게 튀거나 접속이 막힘

증상: 뚝뚝 끊김, 접속 불가·무한 로딩 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

수신 버퍼 넘침 Socket receive buffer overflow

게임이 바빠서 소켓(OS가 제공하는 네트워크 송수신 인터페이스)에서 패킷을 늦게 꺼내면 OS 버퍼가 넘칩니다.

왜: 프레임이 밀려 게임이 소켓을 늦게 읽음 → 그러면: OS 수신 버퍼가 가득 차 UDP는 버리고 TCP는 수신 윈도우를 줄여 송신을 멈추게 함 → 화면에서는: 순간이동(UDP) 또는 몰아치기(TCP)

증상: 순간이동, 몰아치기 · 주 담당 게임개발팀·클라이언트 개발

클라이언트 메모리 부족·스왑 Paging / swap on client

브라우저 탭 수십 개와 게임을 함께 켜 두면 OS가 게임 메모리 일부를 디스크로 내보냅니다.

왜: 전체 램이 부족해짐 → 그러면: OS가 당장 안 쓰는 게임 메모리를 디스크로 옮김 → 화면에서는: 그 부분을 다시 쓰는 순간 저장장치에 따라 수십~수백 ms 멈춤

증상: 멈춤, 뚝뚝 끊김 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

그래픽 메모리(VRAM) 부족 VRAM over-commit

그래픽 옵션이 요구하는 메모리가 그래픽카드 메모리보다 크면, OS가 텍스처를 PC 메모리로 내보냈다가 다시 가져오느라 뚝뚝 끊깁니다.

왜: 높은 텍스처 옵션, 사람 많은 곳의 온갖 장비·이펙트로 그래픽카드 메모리가 가득 참 → 그러면: OS가 당장 안 쓰는 텍스처를 PC 메모리로 옮겼다가, 필요할 때 느린 PCIe 버스로 다시 가져옴 → 화면에서는: 새 장면이나 새 캐릭터가 보일 때마다 멈칫, 텍스처가 한동안 흐릿함

증상: 뚝뚝 끊김, 멈춤 · 주 담당 게임개발팀·클라이언트 개발 · 함께 외부·외부

와이파이 백그라운드 스캔 Periodic Wi-Fi background scan

OS가 주변 와이파이를 찾으려고 주기적으로 채널을 옮겨 다니는 동안 통신이 잠깐 멈춥니다.

왜: OS·드라이버가 일정 주기로 주변 와이파이를 검색 → 그러면: 검색하는 동안 송수신이 잠깐 멈춤 → 화면에서는: 정확히 일정한 간격(예: 60초마다)으로 핑이 튐

증상: 뚝뚝 끊김, 순간이동 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

NIC 절전·드라이버 문제 NIC power saving, driver bugs

랜카드·와이파이 칩이 패킷 사이에 절전 상태로 들어가면 다시 활성화되는 데 시간이 걸립니다.

왜: 네트워크 장치 절전 기능이 켜져 있거나 드라이버가 오래됨 → 그러면: 절전 해제(wake-up) 지연, 가끔 장치 재시작 → 화면에서는: 불규칙한 지연, 드물게 수 초 멈춤

증상: 뚝뚝 끊김, 멈춤 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

같은 기기의 다른 앱이 대역폭 점유 Other apps saturating the link

클라우드 동기화, 대용량 다운로드, 게임 패치가 같은 PC에서 돌면 게임 패킷이 대기열에서 기다립니다.

왜: 다른 앱이 업로드·다운로드를 최대로 사용 → 그러면: PC와 공유기의 대기열에 게임 패킷이 쌓임 → 화면에서는: 핑 폭등, 입력 지연, 몰아치기

증상: 입력 지연, 몰아치기 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

창 최소화·비활성 시 처리 제한 Minimized / unfocused window throttling

다른 창을 보거나 게임을 최소화하면 게임과 윈도우가 전기를 아끼려고 게임을 느리게 돌립니다. 돌아오면 밀린 패킷이 몰려오거나, 이미 접속이 끊겨 있습니다.

왜: Alt+Tab으로 다른 창을 보거나 게임을 최소화 → 그러면: 게임이 보이지 않는 동안 FPS를 크게 낮추거나 멈추고 윈도우도 보이지 않는 프로그램의 우선순위를 낮춤 → 화면에서는: 돌아오는 순간 몰아치기, 오래 내려 두었다면 접속 끊김

증상: 몰아치기, 뚝뚝 끊김, 접속 끊김 · 주 담당 게임개발팀·클라이언트 개발

오버레이 프로그램 간섭 Overlays and screen hooks

메신저·런처·녹화·FPS 표시 프로그램이 게임 화면 위에 자기 UI를 덧그리려고 게임의 렌더링 과정에 끼어듭니다(후킹). 프레임마다 작업이 늘고 가끔 게임과 부딪혀 멈칫하거나 게임이 강제로 꺼집니다.

왜: 메신저·게임 런처·그래픽카드 도구·녹화 프로그램의 오버레이가 켜져 있음 → 그러면: 프레임을 화면에 내보낼 때마다 오버레이가 끼어들어 자기 UI를 덧그림 → 화면에서는: 프레임이 조금씩 늦고 알림이 뜨는 순간 멈칫하거나 그래픽 오류·강제 종료(플레이어에게는 접속 끊김처럼 보임)

증상: 뚝뚝 끊김, 멈춤, 접속 끊김 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

디스플레이·입력 장치·프레임 생성 지연 Display, input device and frame generation latency

핑은 정상인데 조작이 묵직하다면, TV의 영상 처리나 무선 컨트롤러, 프레임 생성 기능이 입력과 화면 사이에 지연을 더했을 수 있습니다.

왜: TV 게임 모드가 꺼져 있거나, 블루투스·무선 컨트롤러를 쓰거나, 프레임 생성(DLSS·FSR 프레임 생성)을 켬 → 그러면: TV는 화질 처리를 하는 동안 프레임을 늦게 내보내고 무선 입력은 전송 주기와 간섭만큼 늦게 도착하며 프레임 생성은 다음 프레임을 기다렸다가 사이 프레임을 만듦 → 화면에서는: 핑과 FPS 숫자는 좋은데 누른 뒤 화면에 반영되기까지 늦어 입력 지연

증상: 입력 지연 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

집 네트워크: 와이파이·공유기·모바일망

패킷이 집을 떠나기 전 마지막 몇 미터입니다. 거리는 짧지만 렉 제보의 상당수가 여기서 생깁니다. 와이파이는 같은 무선 채널을 여러 기기가 나눠 쓰고 공유기는 가족 모두의 트래픽을 하나의 대기열로 내보내기 때문입니다.

와이파이는 같은 무선 채널(주파수 대역)을 이웃 공유기와 나눠 쓰고 2.4GHz 대역은 블루투스·전자레인지와도 겹칩니다. 보내다 부딪히면 잠깐 쉬었다 다시 보내는데 이 재전송이 쌓이면 패킷이 들쭉날쭉 도착합니다. 핑의 평균은 괜찮아 보여도 순간순간 튀는 것이 와이파이의 전형적인 모습입니다.

공유기는 집 안의 모든 기기가 인터넷으로 나갈 때 반드시 거치는 장비입니다. 인터넷 회선이 받아 줄 수 있는 속도보다 많이 보내면 공유기나 모뎀 안에 대기열이 생기는데, 대기열 관리 기능(SQM)이 없는 장비는 이 대기열을 수백 ms 분량까지 길게 쌓아 둡니다. 값비싼 공유기도 이 기능이 꺼져 있으면 마찬가지입니다. 동생이 영상을 올리는 순간 게임 패킷도 그 대기열 맨 뒤에서 기다립니다. 이 현상을 버퍼블로트라고 부릅니다.

공유기는 또 “안쪽 기기 ↔ 바깥 서버” 연결을 NAT 테이블에 기록하는데 한동안 오가는 패킷이 없으면 테이블에서 지워 버립니다. 가만히 있다가 접속이 끊기는 현상의 흔한 원인입니다. 모바일망은 여기에 기지국 전환, 무선 절전 상태, 약한 신호가 더해집니다.

비유

공유기는 아파트 단지의 유일한 출입구입니다. 이삿짐 트럭(영상 업로드)이 줄지어 서 있으면, 급한 오토바이 퀵(게임 패킷)도 트럭 뒤에서 기다려야 합니다. 똑똑한 공유기(SQM)는 퀵 전용 차선을 따로 열어 줍니다.

이 층에서 렉을 만드는 원인

와이파이 간섭·신호 약화 Wi-Fi interference, weak signal

신호가 약하거나 간섭이 생기면 무선 구간에서 몇 번씩 다시 보내느라 도착이 들쭉날쭉해집니다.

왜: 벽·거리·전자레인지·블루투스·이웃 공유기로 전파 품질 저하 → 그러면: 무선 구간에서 전송 실패 → 몇 번씩 재전송 → 화면에서는: 패킷 도착이 들쭉날쭉(지터)해 캐릭터가 멈칫멈칫, 심하면 손실로 순간이동

증상: 뚝뚝 끊김, 순간이동, 고무줄 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

와이파이 채널 혼잡 Crowded Wi-Fi channel

아파트처럼 공유기가 수십 개 있는 곳은 같은 채널을 나눠 쓰느라 전송 기회를 기다립니다.

왜: 수십 개 공유기가 같은 2.4GHz 채널을 사용 → 그러면: 전송하려면 다른 기기의 전송이 끝나 채널이 빌 때까지 대기 → 화면에서는: 사람들이 집에 오는 저녁 시간에 지터(도착 간격의 흔들림)가 늘어 뚝뚝 끊김

증상: 뚝뚝 끊김, 입력 지연 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

버퍼블로트 (공유기 대기열) Bufferbloat

가족 누군가 영상을 올리거나 큰 파일을 받으면 공유기 대기열에 수백 ms 분량의 패킷이 쌓이고, 게임 패킷도 그 뒤에서 기다립니다.

왜: 가족의 영상 업로드·클라우드 백업, 내 방송 송출, 대용량 다운로드로 회선이 꽉 참 → 그러면: 공유기나 모뎀이 넘치는 패킷을 큰 대기열에 쌓아 둠 → 화면에서는: 게임 패킷도 대기열 뒤에서 기다려 핑이 수백 ms로 폭등

증상: 입력 지연, 몰아치기, 순간이동 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

NAT 매핑 만료 NAT mapping timeout

공유기는 한동안 패킷이 오가지 않은 유휴 연결을 NAT 테이블에서 지웁니다. 가만히 있다가 움직이는 순간 접속이 끊기는 흔한 원인입니다.

왜: 공유기가 “안쪽 기기 ↔ 바깥 서버” 연결을 NAT 테이블(주소 변환표)에 기록 → 그러면: 패킷이 한동안 없으면 테이블에서 삭제(UDP는 흔히 30~120초) → 화면에서는: 서버 패킷이 집 안으로 못 들어와 접속 끊김

증상: 접속 끊김 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발

공유기 성능 부족·과열 Router CPU / session table exhaustion

값싼 공유기에 기기 수십 대, 연결 수천 개가 몰리면 공유기 자체가 처리를 못 합니다.

왜: 기기 수십 대, P2P·토렌트가 연결 수천 개를 엶 → 그러면: 공유기 CPU와 세션 테이블이 포화 → 화면에서는: 패킷 처리 지연·손실, 새 연결 실패

증상: 뚝뚝 끊김, 접속 불가·무한 로딩, 접속 끊김 · 주 담당 외부·외부

기지국 핸드오버 (이동 중) Cellular handover

버스·지하철로 이동하면 기지국이 바뀌는 동안 통신이 끊깁니다.

왜: 이동하며 접속하는 기지국이 바뀜 → 그러면: 보통은 수십 ms 공백이지만 신호가 나빠 전환에 실패하면 수백 ms~수 초 끊기기도 함 → 화면에서는: 멈췄다가 순간이동, 길면 접속 끊김

증상: 멈춤, 순간이동, 접속 끊김 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발, 게임개발팀·서버 개발

RRC 상태 전환 지연 (모바일 무선 절전) Radio state promotion (RRC)

폰은 한동안 통신이 없으면 무선 연결을 저전력 상태로 내리고 다음 패킷 때 다시 올리느라 늦어집니다.

왜: 잠시 통신이 없으면 폰이 무선 연결을 절전 상태로 전환 → 그러면: 다음 패킷을 보내려면 연결을 다시 올려야 함 → 화면에서는: 가만히 있다 한 첫 행동만 유독 늦음

증상: 입력 지연 · 주 담당 게임개발팀·클라이언트 개발

모바일 신호 약함·음영 지역 Weak cellular signal

엘리베이터·지하·건물 안쪽에서는 재전송이 늘고 속도가 떨어지며 결국 접속이 끊깁니다.

왜: 신호가 약한 곳으로 이동 → 그러면: 무선 재전송 증가, 속도 저하, 순간 단절 → 화면에서는: 지터·손실로 뚝뚝 끊김·순간이동, 결국 접속 끊김

증상: 뚝뚝 끊김, 순간이동, 접속 끊김 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

5G↔LTE 잦은 전환 (5G 경계 지역) 5G NSA / LTE switching

5G 신호가 약한 건물 안이나 5G 경계 지역에서는 폰이 5G와 LTE를 자주 오가고, 바뀔 때마다 핑이 튀거나 통신이 잠깐 끊깁니다.

왜: 5G 신호가 들쭉날쭉한 곳(건물 안, 5G 경계)에 있음 → 그러면: 폰이 5G와 LTE 사이를 수시로 전환하며 그때마다 짧은 공백이 생김 → 화면에서는: 가만히 있어도 규칙 없이 핑이 튀고 가끔 멈춤·순간이동

증상: 뚝뚝 끊김, 순간이동, 멈춤 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

공용 와이파이·회사망 제한 Captive portal, restrictive network

카페 와이파이 로그인 페이지나 회사 방화벽이 게임 연결을 막습니다.

왜: 로그인 페이지 인증 전이거나 방화벽이 게임 포트·UDP를 차단 → 그러면: 접속 시도 자체가 막히거나 일부만 통과 → 화면에서는: 접속 불가, 로그인은 되는데 게임 입장 실패

증상: 접속 불가·무한 로딩 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발, 게임개발팀·서버 개발

인터넷 회선: 통신사망과 장거리 구간

집을 떠난 패킷은 통신사망과 여러 통신사 사이의 연결 구간, 때로는 해저 케이블을 지나 서버가 있는 데이터센터에 닿습니다. 이 구간의 지연은 대부분 거리와 경로 선택(라우팅)으로 정해지고 게임사가 직접 고칠 수 없는 경우가 많습니다.

빛은 광케이블 안에서 1초에 약 20만 km를 갑니다. 1,000km 떨어진 서버라면 왕복에 최소 10ms가 걸리고 광케이블을 쓰는 한 이 숫자는 서버나 장비를 아무리 좋게 해도 줄일 수 없습니다. 실제 패킷은 직선으로 가지 않고 통신사끼리 연결된 지점(피어링)을 따라 돌아가므로 보통 이론값의 1.5~2배가 걸립니다. 한국–유럽처럼 직선 위로 큰 케이블이 거의 없는 구간은 동남아·수에즈나 미국을 돌아가 2.5~3배(왕복 약 230~270ms)가 됩니다.

이 경로는 시간과 상황에 따라 바뀝니다. 저녁 9~11시 무렵에는 모두가 영상을 보느라 통신사 사이 연결 구간이 붐비기 쉽습니다. 경로 정보(BGP)가 바뀌면 몇 초~몇십 초(드물게 몇 분) 동안 패킷이 목적지에 닿지 못하고 해저 케이블이 끊기면 몇 주 동안 먼 경로로 우회합니다. “특정 통신사 사용자만”, “저녁에만”, “해외에서만” 렉이 있다면 이 층을 먼저 의심합니다.

비유

통신사망은 고속도로망입니다. 서울에서 부산 가는 길이 막히지 않아도 거리만큼은 시간이 걸리고 퇴근 시간 톨게이트(피어링 구간)는 막히며 사고가 나면 내비게이션이 멀리 돌아가는 길을 안내합니다.

이 층에서 렉을 만드는 원인

전파 지연 (물리적 거리) Propagation delay

빛도 광케이블에서 1초에 약 20만 km밖에 못 갑니다. 먼 서버는 아무리 좋아도 늦습니다.

왜: 서버가 멀리 있음 (해외 서버, 다른 대륙) → 그러면: 거리만큼 왕복 시간이 늘어남(1,000km당 최소 10ms) → 화면에서는: 모든 행동에 일정한 입력 지연, 판정에서 불리

증상: 입력 지연 · 주 담당 인프라팀·서버 인프라 · 함께 인프라팀·네트워크 인프라, 게임개발팀·서버 개발

위성 인터넷 (저궤도·정지궤도) Satellite internet (LEO, GEO)

위성 인터넷은 전파가 우주를 오가야 해서, 정지궤도 위성은 왕복만 0.5초가 넘고 Starlink 같은 저궤도 위성은 평소엔 빠르지만 경로를 다시 배정하는 순간 지연이 흔들리고 잠깐 끊기기도 합니다.

왜: 집·배·비행기에서 정지궤도 위성이나 저궤도 위성 인터넷, 위성을 쓰는 기내 와이파이로 접속 → 그러면: 정지궤도는 고도가 약 36,000km라 오가는 거리 자체가 길고 저궤도는 단말·위성·지상국 경로를 짧은 주기로 다시 배정하며 그 순간 지연·손실이 잠깐 생김 → 화면에서는: 정지궤도는 모든 행동에 큰 입력 지연, 저궤도는 평소 괜찮다가 일정한 간격으로 뚝뚝 끊김·순간이동

증상: 입력 지연, 뚝뚝 끊김, 순간이동 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발, 게임개발팀·서버 개발

우회 라우팅 Suboptimal routing

통신사끼리의 연결 계약 때문에 가까운 서버도 먼 곳을 돌아서 갑니다.

왜: 내 통신사와 서버 쪽 통신사가 직접 연결되어 있지 않음 → 그러면: 다른 나라나 다른 도시를 경유해 거리와 장비가 늘어남 → 화면에서는: 특정 통신사 사용자만 핑이 유독 높음

증상: 입력 지연 · 주 담당 인프라팀·네트워크 인프라 · 함께 외부·외부

피크 시간 피어링 구간 혼잡 Peak-hour congestion at peering

저녁 9~11시 무렵에는 영상 트래픽이 폭증해 통신사 간 연결 구간(피어링)이 붐비기 쉽습니다.

왜: 저녁 시간 스트리밍·다운로드가 몰림 → 그러면: 피어링 구간에 대기열과 손실 발생 → 화면에서는: 저녁에만 특정 통신사 사용자가 뚝뚝 끊김·순간이동

증상: 뚝뚝 끊김, 순간이동, 고무줄 · 주 담당 인프라팀·네트워크 인프라 · 함께 외부·외부

해저 케이블·국제 회선 장애 Submarine cable fault

해저 케이블이 끊기면 수리될 때까지 몇 주(길면 몇 달) 동안 먼 우회 경로로 돌아가고, 남은 회선은 붐빕니다.

왜: 케이블 절단·장비 고장 → 그러면: 트래픽이 먼 우회 경로와 남은 회선으로 몰림 → 화면에서는: 해외 접속자 핑 급등과 손실이 며칠~몇 주 지속

증상: 입력 지연, 순간이동 · 주 담당 외부·외부 · 함께 인프라팀·네트워크 인프라

BGP 경로 변경·수렴 Route change / BGP convergence

인터넷의 경로 정보가 바뀌어 다시 수렴하는 몇 초~몇십 초(드물게 몇 분) 동안 패킷이 유실됩니다.

왜: 어느 통신사 구간의 경로 정보가 바뀜 → 그러면: 몇 초~몇십 초 동안 패킷이 사라지거나 새 경로로 전환 → 화면에서는: 갑자기 몇 초 멈춘 뒤 핑 수치가 달라짐(예: 40 → 70ms)

증상: 멈춤, 순간이동 · 주 담당 인프라팀·네트워크 인프라 · 함께 게임개발팀·서버 개발, 외부·외부

ECMP 경로 하나의 불량 ECMP / link bundle member fault

통신사와 데이터센터는 같은 목적지로 가는 경로를 여러 개 두고 연결마다 경로 하나를 정해 보냅니다. 경로 하나만 고장 나면 그 경로에 배정된 사람만 계속 렉을 겪습니다.

왜: 여러 회선을 묶은 구간에서 한 회선이나 장비 하나가 불량이거나 붐빔 → 그러면: 주소·포트 조합(해시)으로 경로가 정해져, 그 경로에 배정된 연결만 손실·지연 → 화면에서는: 같은 지역·같은 통신사인데 일부만 꾸준히 순간이동. 재접속하면 멀쩡해지기도 함

증상: 순간이동, 고무줄, 뚝뚝 끊김 · 주 담당 인프라팀·네트워크 인프라 · 함께 게임개발팀·서버 개발, 외부·외부

통신사 속도 제한·트래픽 관리 Traffic shaping, data caps

데이터 사용량을 넘기거나 특정 트래픽을 관리하는 요금제에서는 패킷이 늦춰지거나 버려집니다.

왜: 요금제 데이터 소진 후 속도 제한, 또는 특정 트래픽 제한 → 그러면: 패킷이 대기하거나 버려짐 → 화면에서는: 일정 사용량 이후 렉, 특히 모바일

증상: 입력 지연, 순간이동 · 주 담당 외부·외부 · 함께 게임개발팀·서버 개발, 인프라팀·네트워크 인프라

국가·통신사 단위 UDP 제한·패킷 검사 UDP blocking, throttling and inspection by networks

일부 망은 특정 UDP 주소·포트를 막거나 UDP 속도를 제한하고 패킷 검사 장비가 알아보지 못하는 프로토콜을 걸러 냅니다. UDP로 통신하는 게임은 그 망에서 접속이 안 되거나 자주 끊깁니다.

왜: UDP 속도를 제한하는 일부 통신사망이나, 국가·통신사 단위의 트래픽 검사(검열) 장비가 있는 망에서 접속 → 그러면: 특정 UDP 주소·포트를 막거나, 붐비는 시간에 UDP 속도를 제한하거나, 허용 목록에 없는 포트·프로토콜을 걸러 내거나, 처음 몇 패킷만 통과시킨 뒤 막음 → 화면에서는: 특정 국가·통신사 유저만 접속 불가·무한 로딩, 접속했다가 곧 접속 끊김, 붐비는 시간에 손실로 순간이동

증상: 접속 불가·무한 로딩, 접속 끊김, 순간이동 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발, 게임개발팀·서버 개발, 인프라팀·네트워크 인프라

회선 품질 불량 Faulty last-mile line / modem

단자 접촉 불량이나 낡은 선, 모뎀 이상은 꾸준한 손실과 주기적인 회선 끊김을 만듭니다.

왜: 케이블 손상, 접촉 불량, 모뎀·광단말 이상 → 그러면: 비트 오류로 패킷 폐기, 가끔 회선이 다시 연결되느라 수 초~1분쯤 단절되기도 함 → 화면에서는: 꾸준한 소량 손실, 가끔 수 초 멈춤이나 접속 끊김

증상: 순간이동, 멈춤, 접속 끊김 · 주 담당 외부·외부

DNS 장애·지연 DNS failure / slowness

서버 이름을 주소로 바꿔 주는 DNS가 느리거나 실패하면 로그인·패치 서버를 찾지 못합니다.

왜: 통신사 DNS 장애 또는 설정 오류 → 그러면: 로그인·패치 서버 주소를 못 찾음 → 화면에서는: 접속 버튼 뒤 한참 대기 또는 접속 불가. 이미 접속한 사람은 멀쩡

증상: 접속 불가·무한 로딩 · 주 담당 외부·외부 · 함께 게임개발팀·클라이언트 개발

DDoS로 인한 공유 회선 포화 DDoS saturating shared links

게임사나 같은 망의 다른 곳을 향한 대량 공격이 공유 회선을 가득 채웁니다.

왜: 대량의 공격 트래픽이 발생 → 그러면: 같은 회선을 쓰는 정상 트래픽까지 밀리고 버려짐 → 화면에서는: 많은 사람이 동시에 순간이동·접속 끊김·접속 불가

증상: 순간이동, 접속 끊김, 접속 불가·무한 로딩 · 주 담당 인프라팀·네트워크 인프라 · 함께 외부·외부

통신사 공유 IP (CGNAT) Carrier-grade NAT

모바일망과 일부 통신사는 여러 가입자가 IP 하나를 나눠 쓰며 유휴 연결의 매핑을 짧은 시간 안에 지웁니다.

왜: 통신사 장비가 수많은 가입자의 세션 테이블을 관리 → 그러면: 세션 테이블 한도, 짧은 유휴 타임아웃 → 화면에서는: 가만히 있다 접속 끊김, 같은 IP를 쓰는 사람들이 한꺼번에 차단되는 오탐

증상: 접속 끊김, 접속 불가·무한 로딩 · 주 담당 게임개발팀·클라이언트 개발 · 함께 게임개발팀·서버 개발, 인프라팀·네트워크 인프라

VPN·게임 가속기 경유 VPN / game accelerator detour

VPN이나 게임 가속기를 켜면 패킷이 그 회사의 중계 서버를 거쳐 갑니다. 중계 서버가 멀거나 붐비면 오히려 느려집니다.

왜: VPN·가속기가 게임 패킷을 모두 중계 서버로 돌려 보냄 → 그러면: 중계 서버까지의 거리와 혼잡이 더해지고 터널 헤더 때문에 MTU(한 번에 보낼 수 있는 패킷 크기)도 줄어듦 → 화면에서는: 핑 상승과 손실, 같은 중계 주소를 쓰는 사람과 함께 차단되어 접속 불가

증상: 입력 지연, 순간이동, 접속 불가·무한 로딩 · 주 담당 외부·외부 · 함께 인프라팀·네트워크 인프라, 게임개발팀·서버 개발

데이터센터 네트워크 장비

서버에 닿기 직전, 패킷은 라우터·DDoS 방어 장비·방화벽·로드밸런서·스위치를 차례로 통과합니다. 평소에는 1ms도 안 걸리는 구간이지만 장비 하나가 용량이 차거나 장애가 나면 서버 전체의 수천 명이 동시에 영향을 받습니다.

각 장비는 역할이 다릅니다. 라우터는 경로를 정하고 DDoS 방어 장비는 공격 트래픽을 걸러 내고 방화벽은 허락된 연결만 통과시키며 모든 연결을 세션 테이블로 추적합니다. 로드밸런서는 들어온 연결을 여러 서버에 나눠 주고 스위치는 서버들을 서로 연결합니다.

이 장비들의 공통 약점은 테이블 크기와 버퍼 크기입니다. 방화벽 세션 테이블이 가득 차면 새 연결을 못 받고 로드밸런서는 유휴 연결을 일정 시간 뒤 지워 버립니다. 스위치의 작은 버퍼는 여러 서버가 같은 순간 수천 명에게 패킷을 한꺼번에 보낼 때(월드 보스 등장) 1ms도 안 돼 넘칩니다. 장비 한 대가 고장 나 예비 장비로 전환(페일오버)되는 몇 초 동안에도 모두가 멈춥니다.

비유

데이터센터 입구는 공항 보안 검색대와 탑승 게이트입니다. 검색대(방화벽)는 명단에 있는 사람만 통과시키고 명단 칸이 다 차면 더 못 받습니다. 게이트 직원(로드밸런서)은 한참 조용히 앉아 있는 승객을 “떠난 사람”으로 치고 명단에서 지웁니다.

이 층에서 렉을 만드는 원인

방화벽 세션 테이블 포화 Firewall session table exhaustion

방화벽은 통과시킨 모든 연결을 세션 테이블에 기록해 추적합니다. 테이블이 다 차면 새 연결을 받을 수 없습니다.

왜: 접속 폭주나 공격으로 세션 수가 한도에 도달 → 그러면: 새 연결을 기록할 빈 항목이 없어 거부 → 화면에서는: 새로 들어오려는 사람은 접속 불가·무한 로딩, 일부 기존 연결도 접속 끊김

증상: 접속 불가·무한 로딩, 접속 끊김 · 주 담당 인프라팀·네트워크 인프라 · 함께 게임개발팀·서버 개발, 게임개발팀·클라이언트 개발

DDoS 방어 경유·오탐 DDoS scrubbing latency, false positives

공격을 막으려고 트래픽을 스크러빙 센터로 돌리면 경로가 길어지고 정상 사용자를 공격으로 오인해 막기도 합니다.

왜: 공격 감지 후(또는 상시) 들어오는 트래픽을 스크러빙 센터로 우회 → 그러면: 경로가 길어지고 일부 정상 패킷을 공격으로 판정 → 화면에서는: 전체 핑 상승, 특정 지역·통신사만 접속 불가

증상: 입력 지연, 접속 불가·무한 로딩, 순간이동 · 주 담당 인프라팀·네트워크 인프라 · 함께 게임개발팀·서버 개발

로드밸런서 유휴 타임아웃 Load balancer idle timeout

로드밸런서는 유휴 연결을 일정 시간 뒤 지웁니다. 게임은 연결이 유지된다고 여기다가 접속이 끊깁니다.

왜: 플레이어가 한동안 아무 패킷도 안 보냄(대화창, 자리 비움) → 그러면: 로드밸런서가 유휴 연결을 정리(흔한 기본값 60~350초) → 화면에서는: 다시 움직이는 순간 접속 끊김

증상: 접속 끊김 · 주 담당 인프라팀·네트워크 인프라 · 함께 게임개발팀·클라이언트 개발, 게임개발팀·서버 개발

클라우드 보안 그룹의 연결 추적 만료 Cloud security group connection tracking timeout

클라우드 서버에 붙은 방화벽(보안 그룹)도 연결을 추적하고 유휴 연결의 추적 항목은 정해진 시간 뒤 만료됩니다. 로드밸런서 없이 바로 붙는 서버에서도 가만히 있던 플레이어의 접속이 끊길 수 있습니다.

왜: 보안 그룹이 게임 연결을 추적하는 설정(특정 주소만 허용, 나가는 규칙 제한, NLB 경유 등) → 그러면: 한동안 유휴 상태인 연결의 추적 항목이 만료되고 그 뒤 오는 패킷을 보안 그룹이 조용히 버림 → 화면에서는: 자리 비움 뒤 다시 움직이면 반응이 없다가 접속 끊김. 서버 프로그램은 한참 모름

증상: 접속 끊김 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·클라이언트 개발, 게임개발팀·서버 개발

클라우드 NAT 게이트웨이 연결·포트 한도 Cloud NAT gateway connection / port limits

사설 서브넷의 서버가 외부(플랫폼 인증·결제·외부 API)로 나가는 연결은 NAT 게이트웨이가 주소와 포트를 바꿔 내보냅니다. 같은 목적지로 가는 동시 연결이 게이트웨이의 포트 한도를 넘으면 새 연결이 실패합니다.

왜: 서버들이 플랫폼 인증·결제처럼 같은 외부 주소로 짧은 연결을 많이 열거나 연결을 오래 열어 둠 → 그러면: NAT 게이트웨이가 그 목적지에 쓸 원본 포트를 더 할당하지 못해 새 연결이 실패함 → 화면에서는: 게임 안은 멀쩡한데 로그인·결제·보상 지급처럼 외부를 부르는 기능만 실패하거나 늦어짐(접속 불가·무한 로딩, 씹힘·롤백)

증상: 접속 불가·무한 로딩, 씹힘·롤백 · 주 담당 인프라팀·네트워크 인프라 · 함께 게임개발팀·서버 개발

로드밸런서 쏠림·헬스체크 오판 LB imbalance, bad health checks

로드밸런서가 한 서버에만 연결을 몰아주거나, 이미 죽은 서버로 계속 사람을 보냅니다.

왜: 분배 규칙이 맞지 않거나 헬스체크가 실제 상태를 못 봄 → 그러면: 한 서버만 과부하, 또는 죽은 서버로 접속 시도 → 화면에서는: 일부 채널·일부 사람만 슬로우모션, 접속 불가·무한 로딩

증상: 슬로우모션, 접속 불가·무한 로딩 · 주 담당 인프라팀·네트워크 인프라 · 함께 게임개발팀·서버 개발

스위치 마이크로버스트 Switch microburst drops

여러 서버가 같은 순간 수천 명에게 패킷을 한꺼번에 보내면, 그 트래픽이 모이는 스위치 포트의 작은 버퍼가 1ms도 안 돼 넘칩니다.

왜: 월드 보스 등장·대규모 스킬, 또는 여러 서버의 틱이 같은 순간에 맞물려 한꺼번에 발송 → 그러면: 여러 포트가 한 포트로 모이거나 빠른 포트에서 느린 포트로 넘어가는 곳의 버퍼(포트당 수백 KB~수 MB)가 순간적으로 가득 → 화면에서는: 일부 패킷 폐기, 많은 사람이 동시에 순간이동·스킬 씹힘

증상: 순간이동, 씹힘·롤백 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·네트워크 인프라, 인프라팀·서버 인프라

데이터센터 회선 포화 Uplink saturation

패치 배포·로그 전송·백업이 게임과 같은 회선을 쓰면 회선이 꽉 찹니다.

왜: 대용량 전송이 같은 회선을 점유 → 그러면: 회선 대기열과 손실 증가 → 화면에서는: 서버 전체 핑 상승과 순간이동

증상: 입력 지연, 순간이동 · 주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라

네트워크 장비 장애 전환(페일오버) Network device failover

라우터·방화벽 한 대가 고장 나 예비 장비로 전환(페일오버)되는 몇 초 동안 모두가 멈춥니다.

왜: 장비 고장 또는 점검으로 예비 장비로 전환 → 그러면: 전환에 수 초, 세션 정보가 동기화되지 않으면 연결 초기화 → 화면에서는: 서버의 모든 유저가 동시에 멈춤, 대량 접속 끊김

증상: 멈춤, 접속 끊김 · 주 담당 인프라팀·네트워크 인프라 · 함께 게임개발팀·서버 개발, 게임개발팀·클라이언트 개발

불량 케이블·포트 오류 Bad cable / optics (CRC errors)

광모듈이나 케이블이 불량이면 그 경로를 지나는 패킷이 일정 비율로 깨집니다.

왜: 광모듈·케이블 불량으로 비트 오류 → 그러면: 깨진 패킷은 장비가 조용히 폐기 → 화면에서는: 그 경로를 쓰는 일부 서버·사용자만 꾸준한 손실로 순간이동·고무줄

증상: 순간이동, 고무줄 · 주 담당 인프라팀·네트워크 인프라

MTU 불일치 (큰 패킷만 사라짐) MTU black hole

중간 구간의 MTU(한 번에 보낼 수 있는 크기)가 줄었는데 크기 초과 알림이 막히면, 큰 패킷만 계속 사라집니다.

왜: 터널·VPN 구간에서 MTU가 줄어듦 → 그러면: 크기 초과 알림(ICMP)이 방화벽에 막혀 보내는 쪽이 모름 → 화면에서는: 인벤토리·캐릭터 목록처럼 큰 화면을 열 때만 멈췄다가 접속 끊김

증상: 멈춤, 접속 끊김, 접속 불가·무한 로딩 · 주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라, 게임개발팀·서버 개발

서버 네트워크 카드(NIC)

서버에 꽂힌 네트워크 카드는 초당 수십만~수백만 개의 패킷을 받아 CPU에 넘깁니다. 여기서 처리가 밀리면 서버 프로그램은 패킷이 온 줄도 모른 채 잃어버립니다.

NIC는 도착한 패킷을 링 버퍼(정해진 개수의 슬롯을 돌려 쓰는 수신 버퍼)에 차례로 담고 CPU에게 “패킷 왔어요” 하고 알립니다(인터럽트). CPU는 링 버퍼에서 패킷을 꺼내 OS로 넘깁니다. CPU가 꺼내는 속도보다 빨리 들어오면 슬롯이 모두 차고 그 뒤로 오는 패킷은 버려집니다. 네트워크 카드 통계(ethtool -S)의 숫자만 조용히 올라갈 뿐 게임 서버 로그에는 아무 오류도 남지 않아 찾기 어려운 렉입니다.

요즘 NIC는 수신 큐(링 버퍼)를 여러 개 두고 여러 CPU 코어에 나눠 알리는 기능(RSS)이 있지만 설정이 안 되어 있거나 트래픽이 한 큐로 쏠리면 코어 하나만 100%가 되어 병목이 됩니다. 클라우드 서버라면 NIC 앞에 초당 패킷 수·대역폭·연결 수 한도가 따로 있어, 넘치는 만큼 서버에 닿기 전에 버려집니다. CPU·링 버퍼 같은 평소 지표에는 드러나지 않고 AWS라면 ENA 드라이버 통계(ethtool -S의 pps_allowance_exceeded 등)에만 남습니다.

비유

NIC는 아파트 우편함, 링 버퍼는 우편함 칸 수, 인터럽트는 집배원의 초인종입니다. 우편물이 쏟아지는데 꺼내는 사람이 한 명뿐이면 칸이 넘쳐 편지가 바닥에 떨어집니다. RSS는 꺼내는 사람을 여럿 두는 방식입니다.

이 층에서 렉을 만드는 원인

NIC 인터럽트 단일 코어 집중 Single-queue NIC / no RSS

NIC가 패킷 도착 인터럽트를 CPU 코어 하나에만 보내면 그 코어가 병목이 됩니다.

왜: 수신 큐가 하나이거나 여러 코어로 분산하는 RSS가 꺼져 있음 → 그러면: 코어 하나가 100%가 되어 패킷을 제때 못 꺼냄 → 화면에서는: 사람이 몰릴 때 서버 전체에서 손실과 지연(순간이동·입력 지연)

증상: 순간이동, 고무줄, 입력 지연 · 주 담당 인프라팀·서버 인프라

링 버퍼 부족 RX ring buffer overflow

NIC가 패킷을 잠시 담아 두는 링 버퍼가 작으면, 순간적으로 몰릴 때 버퍼가 넘쳐 패킷이 버려집니다.

왜: 링 버퍼가 기본값(드라이버마다 슬롯 256~2,048개)으로 작음 → 그러면: 버스트 때 CPU가 꺼내기 전에 버퍼가 넘침 → 화면에서는: 버스트 순간에만 손실(순간이동·스킬 씹힘). 게임 서버 로그에는 흔적이 없음

증상: 순간이동, 씹힘·롤백 · 주 담당 인프라팀·서버 인프라

인터럽트 병합 과다 Interrupt coalescing

CPU 부담을 줄이려고 패킷을 모았다 한 번에 알리면, 모으는 시간만큼 늦어집니다.

왜: NIC가 일정 시간·개수만큼 모았다가 알림 → 그러면: 모으는 동안 패킷이 대기 → 화면에서는: 미세한 지연 증가. 보통은 작지만 과하면 ms 단위

증상: 입력 지연 · 주 담당 인프라팀·서버 인프라

클라우드 PPS 한도 초과 Cloud PPS / bandwidth allowance

클라우드 서버는 종류마다 초당 패킷 수·대역폭 한도가 있고 넘으면 조용히 버립니다.

왜: 동접이 늘어 초당 패킷 수가 인스턴스 한도를 넘음 → 그러면: 클라우드 네트워크가 초과분을 폐기 → 화면에서는: 원인을 알 수 없는 손실로 순간이동·스킬 씹힘. 서버 CPU는 여유

증상: 순간이동, 씹힘·롤백 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발, 외부·외부

NIC 대역폭 포화 NIC bandwidth saturation

1Gbps·10Gbps 카드의 한계까지 쓰면 송신 대기열이 길어지고 넘친 패킷은 버려집니다.

왜: 브로드캐스트 증가로 전송량이 카드 한계에 도달 → 그러면: 송신 대기열이 길어지고 넘치면 폐기 → 화면에서는: 서버 전체 지연·손실(입력 지연·순간이동)

증상: 입력 지연, 순간이동 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

가상화 오버헤드·노이지 네이버 Noisy neighbors in virtualization

같은 물리 서버의 다른 가상 머신이 네트워크·CPU를 많이 쓰면 내 서버의 처리가 불규칙하게 밀립니다.

왜: 같은 물리 서버의 다른 가상 머신이 자원을 많이 씀 → 그러면: 내 가상 머신의 패킷 처리가 불규칙하게 지연 → 화면에서는: 뚜렷한 원인 없이 가끔 지터(도착 간격의 흔들림)가 생겨 뚝뚝 끊김

증상: 뚝뚝 끊김 · 주 담당 인프라팀·서버 인프라 · 함께 외부·외부

클라우드 호스트 점검·라이브 마이그레이션 Cloud host maintenance / live migration

클라우드 사업자가 물리 서버(호스트)를 점검할 때 가상 머신을 다른 호스트로 옮기거나(라이브 마이그레이션) 잠시 멈춥니다. 그동안 서버 전체가 멈추고 멈춘 시간이 길면 연결이 끊깁니다.

왜: 사업자가 호스트 점검이나 고장 예측으로 가상 머신을 다른 호스트로 옮기거나 잠시 일시 정지 → 그러면: 옮기는 동안 CPU·메모리·네트워크가 느려지고 마지막에 가상 머신이 잠깐 완전히 멈춤(사업자와 방식에 따라 1초 미만에서 30초 안팎) → 화면에서는: 서버의 모두가 동시에 멈췄다가 몰아치기·순간이동, 멈춤이 타임아웃보다 길면 대량 접속 끊김

증상: 멈춤, 몰아치기, 순간이동, 접속 끊김 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발, 외부·외부

NIC 드라이버·펌웨어 문제 NIC hang / reset

드라이버 버그나 기능 오동작으로 카드가 멈춰 재시작되는 동안 모든 송수신이 끊깁니다.

왜: 드라이버 버그, 오프로드 기능 오동작 → 그러면: NIC가 멈추고 재시작(수 초) → 화면에서는: 그 서버의 모두가 함께 멈췄다가 순간이동하거나 접속 끊김

증상: 멈춤, 접속 끊김 · 주 담당 인프라팀·서버 인프라

GRO/LRO 병합 대기 지연 GRO/LRO batching

여러 패킷을 하나로 묶어 CPU 부담을 줄이는 기능입니다. 설정에 따라 작은 게임 패킷이 함께 묶을 다음 패킷을 잠깐 기다리기도 합니다.

왜: NIC·커널이 도착한 패킷을 묶어서 처리 → 그러면: 하드웨어 병합(LRO)이나 병합 대기 시간 설정이 켜져 있으면 다음 패킷을 기다리며 잠깐 대기 → 화면에서는: 미세한 지연 증가(대개 수십 µs 이하)

증상: 입력 지연 · 주 담당 인프라팀·서버 인프라

서버 OS (커널)

서버의 리눅스·윈도우 커널은 연결을 받아 주고 소켓 버퍼를 관리하고 CPU와 메모리를 게임 서버 프로그램에 나눠 줍니다. 대부분의 기본값은 여러 용도에 두루 맞춘 보수적인 값이라, 수만 명이 오래 접속해 있는 게임 서버에는 그대로 맞지 않는 경우가 많습니다.

새 접속이 들어오면 커널은 접속 요청을 접속 대기열(backlog)에 넣어 두고 게임 서버가 하나씩 받아 갑니다. 대기열이 차면 리눅스는 새 요청을 말없이 버리고 윈도우는 거절 응답을 돌려보냅니다. 리눅스에서는 연결마다 열린 파일·연결에 붙는 번호인 파일 디스크립터(fd)가 하나씩 필요한데, 한 프로세스가 가질 수 있는 fd 수에도 한도가 있습니다. 점검 직후 수만 명이 동시에 접속 버튼을 누르면 접속 대기열과 fd가 가장 먼저 바닥납니다.

커널은 또 메모리가 모자라면 디스크로 내보내고(스왑, 켜 둔 경우), 리눅스는 완전히 바닥나면 메모리를 가장 많이 쓰는 프로세스를 골라 강제로 죽입니다(OOM 킬러). 게임 서버는 대개 그 서버에서 메모리를 가장 많이 쓰는 프로세스라 가장 먼저 종료 대상이 됩니다. 컨테이너에 메모리 한도를 걸어 두었다면 서버 전체에 여유가 있어도 한도에 닿는 순간 같은 일이 생깁니다. 시간 동기화(NTP), 예약 작업, 컨테이너 CPU 한도, 가상 머신의 CPU 스틸(다른 가상 머신이 물리 CPU를 쓰는 동안 기다리는 시간)처럼 게임과 상관없어 보이는 일도 서버를 잠깐씩 멈추거나 타이머를 어긋나게 합니다.

비유

서버 OS는 놀이공원의 입장 게이트와 관리 사무소입니다. 개장 시간(점검 종료)에 모두가 몰리면 게이트 앞 줄(backlog)이 넘치고, 발급할 손목밴드(파일 디스크립터)가 떨어지면 더 못 들어옵니다.

이 층에서 렉을 만드는 원인

접속 대기열(backlog) 넘침 Listen backlog / SYN queue overflow

점검 직후 수만 명이 동시에 접속하면, 커널의 접속 대기열(backlog)이 넘쳐 접속 시도가 버려집니다.

왜: 점검 종료와 동시에 게임 서버가 accept로 접속을 처리하는 속도보다 빨리 몰림 → 그러면: 커널의 접속 대기열(backlog. 서버 코드가 listen에 준 값과 커널 상한 중 작은 쪽)이 가득 → 화면에서는: 접속 시도가 버려지고 재시도가 반복되어 접속 불가·무한 로딩

증상: 접속 불가·무한 로딩 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라, 게임개발팀·클라이언트 개발

파일 디스크립터 한도 File descriptor limit (ulimit)

연결 하나마다 파일 디스크립터(fd, OS가 열린 파일·소켓에 붙이는 번호)가 필요한데, 한 프로세스가 열 수 있는 fd 수가 제한되어 있습니다.

왜: 동접이 프로세스의 파일 디스크립터 한도에 도달 → 그러면: 서버가 새 연결을 받지 못함(Too many open files). 로그·DB 연결 열기도 함께 실패 → 화면에서는: 정확히 일정 인원부터 아무도 못 들어오는 접속 불가·무한 로딩

증상: 접속 불가·무한 로딩 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발

커널 소켓 버퍼 부족 Small socket buffers

송수신 버퍼가 작으면 버스트 트래픽이 몰릴 때 UDP로 받은 패킷은 버려지고, TCP 송신은 버퍼에 여유가 없어 막힙니다.

왜: SO_SNDBUF·SO_RCVBUF가 기본값이거나 너무 작음 → 그러면: 버스트나 받는 스레드가 잠깐 멈춘 사이 UDP 수신 버퍼가 넘쳐 폐기, TCP는 송신 버퍼에 여유가 없어 대기 → 화면에서는: 순간이동(UDP 손실) 또는 몰아치기(TCP 대기)

증상: 순간이동, 몰아치기 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발

스레드 과다와 컨텍스트 스위칭 Thread oversubscription, context switching

코어보다 훨씬 많은 스레드를 돌리면 OS가 번갈아 실행시키는 데만 CPU를 씁니다.

왜: 연결마다 스레드를 만드는 등 스레드가 수백~수천 개 → 그러면: 컨텍스트 스위칭(실행 스레드 교체) 비용과 캐시 미스 증가 → 화면에서는: CPU는 바쁜데 처리량은 낮고 틱이 들쭉날쭉해 뚝뚝 끊김·슬로우모션

증상: 뚝뚝 끊김, 슬로우모션 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

CPU 스틸 (가상 머신) CPU steal time

물리 서버(하이퍼바이저)가 가상 머신의 CPU 시간을 잠시 다른 가상 머신에 넘기는 동안(CPU 스틸) 게임 서버가 멈춥니다.

왜: 같은 호스트의 다른 가상 머신이 CPU를 많이 씀 → 그러면: 내 가상 머신이 수 ms~수십 ms씩 실행 기회를 잃음 → 화면에서는: 원인 모를 틱 시간 급증으로 뚝뚝 끊김·멈춤

증상: 뚝뚝 끊김, 멈춤 · 주 담당 인프라팀·서버 인프라 · 함께 외부·외부

컨테이너 CPU 스로틀링 (CFS 쿼터) Container CPU throttling (CFS quota)

컨테이너에 CPU 한도를 걸면, 정해진 주기(보통 100ms) 안에 할당량을 다 쓴 순간 남은 시간 동안 강제로 멈춥니다(스로틀링).

왜: 쿠버네티스 등에서 게임 서버 컨테이너에 CPU 한도(limit)를 걸어 둠 → 그러면: 틱 계산이 몰린 순간 할당량을 다 써서 다음 주기까지 수십 ms 정지 → 화면에서는: 평균 CPU는 낮은데 틱이 주기적으로 튀어 뚝뚝 끊김·슬로우모션

증상: 뚝뚝 끊김, 슬로우모션 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발

서버 전원 관리(C-state·주파수 조절)로 지연 튐 CPU power management latency (C-states, frequency scaling)

쉬는 CPU 코어는 전기를 아끼려고 깊은 절전 상태(C-state)로 들어가고 주파수도 낮춥니다. 패킷이나 타이머가 오면 깨어나고 주파수를 올리는 데 시간이 걸려, 작은 패킷 처리에 지연이 더해집니다.

왜: OS의 주파수 조절 정책(governor)이나 BIOS 전원 설정이 깊은 C-state와 낮은 주파수를 허용 → 그러면: 쉬던 코어가 깊은 절전 상태에서 깨어날 때마다 최대 수백 µs 늦고 주파수가 낮게 묶여 있으면 틱 계산 자체가 느려짐 → 화면에서는: 대개 체감하기 어렵지만 서버 간 호출이 많으면 쌓여 한산할 때 오히려 응답이 늦는 입력 지연. 주파수가 낮게 묶이면 사람이 몰릴 때 틱이 밀려 슬로우모션

증상: 입력 지연, 슬로우모션 · 주 담당 인프라팀·서버 인프라

OOM 킬러 Out-of-memory killer

리눅스는 메모리가 바닥나면 메모리를 가장 많이 쓰는 프로세스를 골라 강제로 죽입니다. 대개 게임 서버입니다.

왜: 누수나 폭증으로 메모리 고갈, 또는 컨테이너 메모리 한도 도달 → 그러면: 커널이 게임 서버 프로세스를 강제 종료 → 화면에서는: 그 서버의 모두가 동시에 접속 끊김, 최근 진행 롤백 가능

증상: 접속 끊김, 씹힘·롤백 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

메모리 회수·컴팩션으로 인한 멈춤 Memory compaction / reclaim stalls (THP)

OS가 큰 페이지(huge page)를 만들려고 메모리를 컴팩션하거나 여유 메모리를 회수하는 동안 프로세스가 멈춥니다.

왜: 여유 메모리가 줄거나 큰 페이지 기능(THP)이 메모리 컴팩션 실행 → 그러면: 메모리를 요청한 스레드가 회수·컴팩션이 끝날 때까지 대기 → 화면에서는: 불규칙한 서버 멈춤(수 ms~수백 ms)

증상: 멈춤, 뚝뚝 끊김 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발

시스템 시계 점프 (NTP 스텝) Wall-clock jump (NTP step)

서버 시계가 한 번에 몇 초 앞뒤로 조정되면 시스템 시계에 의존하는 타이머가 한꺼번에 발동하거나 멈춥니다.

왜: 시간 동기화가 시계를 한 번에 크게 조정 → 그러면: 타이머가 몰아서 발동하거나 멈추고 타임아웃이 잘못 판정됨 → 화면에서는: 버프·쿨타임 이상, 일제히 접속 끊김, 몰아치기

증상: 몰아치기, 접속 끊김, 씹힘·롤백 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

예약 작업 Cron jobs (log rotation, backup, scans)

매일 같은 시각에 도는 로그 압축·백업·보안 검사가 CPU와 디스크를 차지합니다.

왜: 정해진 시각에 OS 작업이 실행 → 그러면: CPU·디스크를 게임 서버와 나눠 씀 → 화면에서는: 매일 새벽 4시처럼 정해진 시각에 뚝뚝 끊김·슬로우모션

증상: 뚝뚝 끊김, 슬로우모션 · 주 담당 인프라팀·서버 인프라

OS·커널·드라이버·펌웨어 업데이트 뒤 성능 변화 Performance regression after OS / kernel / driver / firmware update

게임 코드는 그대로인데 서버 OS·커널·드라이버·펌웨어를 업데이트한 뒤부터 서버가 느려집니다. 업데이트로 기본값, 스케줄러, CPU 취약점 완화(mitigations), 드라이버 동작이 바뀌기도 합니다.

왜: 정기 보안 패치나 새 서버 이미지로 커널·드라이버·펌웨어가 바뀜 → 그러면: 기본값·스케줄러가 바뀌거나 새 취약점 완화가 켜져, 같은 일에 CPU 시간이 더 들고 스레드가 CPU를 배정받는 순서가 달라짐 → 화면에서는: 잘되던 서버가 업데이트한 날부터 늘 조금씩 느려져 입력 지연, 사람이 몰리면 뚝뚝 끊김·슬로우모션

증상: 입력 지연, 뚝뚝 끊김, 슬로우모션 · 주 담당 인프라팀·서버 인프라

서버 conntrack 테이블 포화 conntrack table full

리눅스 방화벽이 모든 연결을 기록하는 연결 추적(conntrack) 테이블이 한도에 닿으면 새 패킷을 버립니다.

왜: 접속 폭주, 짧은 연결 반복으로 연결 기록 증가 → 그러면: 테이블이 가득 차 새 연결과 일부 패킷 폐기 → 화면에서는: 접속 불가, 원인 모를 손실로 순간이동

증상: 접속 불가·무한 로딩, 순간이동 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발, 게임개발팀·클라이언트 개발

서버 간 연결의 임시 포트 고갈 Ephemeral port exhaustion (TIME_WAIT)

게임 서버가 DB나 다른 서버에 연결을 짧게 자주 맺고 끊으면, 끊긴 연결이 한동안 포트를 점유해 새 연결을 못 엽니다.

왜: 요청마다 새 연결을 열고 닫음 → 그러면: 먼저 닫은 쪽이 약 60초(리눅스) 동안 포트를 점유해(TIME_WAIT) 쓸 포트가 바닥 → 화면에서는: 내부 요청 실패로 저장 실패·기능 오류

증상: 씹힘·롤백, 접속 불가·무한 로딩 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

소켓과 프로토콜: TCP, UDP, 소켓 옵션

게임이 네트워크로 데이터를 주고받는 방식을 정하는 부분입니다. 같은 회선이라도 어떤 프로토콜을 쓰고 소켓 옵션을 어떻게 켜느냐에 따라, 패킷 하나를 잃었을 때 “살짝 튄다”로 끝날 수도, “1초 멈췄다 몰아친다”가 될 수도 있습니다.

TCP는 보낸 순서대로, 빠짐없이 전달하는 것을 보장합니다. 대신 하나를 잃으면 다시 받을 때까지 뒤에 도착한 것까지 전부 게임에 넘기지 않고 기다립니다. UDP는 아무것도 보장하지 않습니다. 도착한 것은 기다림 없이 바로 넘겨주지만 잃어버린 것은 게임이 알아서 처리해야 합니다. 그래서 액션성이 강한 게임은 UDP 위에 필요한 만큼만 신뢰성을 직접 구현하고(신뢰성 UDP), 많은 MMO는 구현이 쉬운 TCP를 쓰면서 그 약점을 감수합니다.

소켓 옵션은 이 동작의 세부 설정입니다. 작은 패킷을 모았다 보낼지(TCP_NODELAY), 송수신 버퍼를 얼마나 둘지(SO_SNDBUF, SO_RCVBUF), 죽은 연결을 언제 알아챌지(SO_KEEPALIVE, TCP_USER_TIMEOUT), 닫을 때 남은 데이터를 어떻게 할지(SO_LINGER). 기본값은 대부분 큰 데이터를 적은 패킷으로 효율 있게 보내는 쪽에 맞춰져 있어, 작은 패킷을 자주 주고받는 게임에는 불리한 경우가 많습니다.

핵심

TCP는 받은 데이터를 보낸 순서대로만 게임에 넘겨줍니다. 17번 패킷이 사라지면 18~30번이 이미 도착해 있어도, 17번이 다시 올 때까지 모두 기다립니다(HOL 블로킹). UDP는 도착하는 대로 넘겨주므로 17번이 끝내 오지 않아도 나머지는 제때 처리됩니다.

재전송이 왜 생기는지(와이파이, 혼잡, MTU 블랙홀, 불필요한 재전송 등)와 원인을 찾는 방법은 06 TCP 재전송에서 원인별로 다룹니다.

이 층에서 렉을 만드는 원인

TCP HOL 블로킹 Head-of-line blocking

TCP는 순서를 지키려고 잃어버린 패킷 하나를 다시 받을 때까지 뒤에 도착한 패킷을 게임에 넘기지 않습니다.

왜: 패킷 하나가 사라짐 → 그러면: 뒤 패킷들은 도착했지만 수신 버퍼에서 대기 → 화면에서는: 멈췄다가 한꺼번에 풀리며 몰아치기

증상: 멈춤, 몰아치기 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

TCP RTO와 지수 백오프 RTO and exponential backoff

재전송이 또 실패할 때마다 기다리는 시간이 두 배로 늘어, 짧은 회선 끊김이 긴 멈춤이 됩니다.

왜: 회선이 잠깐 끊겨 재전송도 연달아 실패 → 그러면: 다음 시도까지 0.3 → 0.6 → 1.2 → 2.4초처럼 두 배씩 늘어남(핑 100ms 기준) → 화면에서는: 회선은 1초 끊겼는데 게임은 2초 넘게 멈춤. 더 길게 끊기면 결국 접속 끊김

증상: 멈춤, 접속 끊김 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

Nagle 알고리즘 + 지연 ACK Nagle + delayed ACK (TCP_NODELAY off)

작은 패킷을 모아 보내는 Nagle 알고리즘과 ACK를 늦게 보내는 지연 ACK가 맞물려, 메시지를 나눠 쓸 때마다 40~200ms씩 지연됩니다.

왜: TCP_NODELAY를 켜지 않은 채 작은 메시지를 나눠 씀 → 그러면: 보내는 쪽은 ACK를 기다리고 받는 쪽은 ACK를 늦게 보냄 → 화면에서는: 회선 핑은 낮은데 모든 행동이 일정하게 굼뜬 입력 지연

증상: 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

느린 클라이언트로 인한 블로킹 전송 Blocking send on a full socket

회선이 느린 한 명의 송신 버퍼가 가득 찼는데 블로킹 방식(버퍼에 여유가 생길 때까지 호출이 반환되지 않는 전송)으로 보내면, 서버 스레드가 그 한 명을 기다립니다.

왜: 느린 클라이언트의 송신 버퍼가 가득 → 그러면: 블로킹 전송이라 서버 스레드가 버퍼에 여유가 생길 때까지 대기 → 화면에서는: 그 스레드가 맡은 모두가 멈춤·슬로우모션

증상: 멈춤, 슬로우모션 · 주 담당 게임개발팀·서버 개발

느린 클라이언트(slow consumer) 처리 정책 Slow-consumer policy

보낼 게 계속 쌓이는 클라이언트에게 서버가 오래된 업데이트를 버리거나 연결을 끊습니다.

왜: 클라이언트의 회선이 서버가 보내는 양을 못 따라감 → 그러면: 서버가 오래된 업데이트를 버리거나 한도 초과 시 연결 해제 → 화면에서는: 그 사람만 순간이동 또는 접속 끊김

증상: 순간이동, 접속 끊김 · 주 담당 게임개발팀·서버 개발

keepalive 기본값 2시간 TCP keepalive defaults

상대가 종료 신호 없이 사라지면 TCP는 한참 뒤에야 감지합니다. keepalive(유휴 연결이 살아 있는지 확인하는 TCP 기능)는 기본으로 꺼져 있고, 켜도 2시간 동안 유휴 상태여야 확인을 시작합니다.

왜: 클라이언트가 전원 꺼짐·회선 끊김으로 종료 신호 없이 사라짐 → 그러면: 서버는 연결이 살아 있다고 간주(keepalive 기본 7,200초. 보내던 데이터가 있으면 재전송 포기까지 약 15분) → 화면에서는: 유령 캐릭터가 남고 재접속하면 “이미 접속 중” 오류

증상: 접속 불가·무한 로딩, 안 보임·유령 개체 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발, 인프라팀·서버 인프라

UDP 패킷의 IP 단편화 IP fragmentation of large UDP

MTU(한 번에 보낼 수 있는 크기)를 넘는 UDP 패킷은 IP 계층에서 단편화되고, 프래그먼트 하나만 잃어도 전체가 버려집니다.

왜: 사람 많은 곳의 스냅샷이 1,500바이트를 넘음 → 그러면: 여러 프래그먼트로 나뉘어 전송, 하나라도 잃으면 전체 폐기 → 화면에서는: 큰 패킷일수록 손실률이 몇 배. 붐비는 곳에서만 순간이동

증상: 순간이동 · 주 담당 게임개발팀·서버 개발

신뢰성 UDP 재전송 설정 Reliable-UDP tuning (KCP, ENet…)

UDP 위에 직접 만든 재전송 규칙이 너무 보수적이면 복구가 늦고 너무 공격적이면 회선을 더 막습니다.

왜: 재전송 간격·횟수·윈도우 크기 설정이 회선과 맞지 않음 → 그러면: 늦은 복구, 또는 중복 전송으로 혼잡 악화 → 화면에서는: 스킬 씹힘, 몰아치기, 혼잡 시 더 심한 렉

증상: 씹힘·롤백, 몰아치기 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

유휴 후 슬로 스타트 Slow start after idle

TCP는 한동안 유휴 상태면 혼잡 윈도우(한 번에 보낼 수 있는 양)를 다시 줄여, 갑자기 큰 데이터를 보낼 때 여러 번에 나눠 보냅니다.

왜: 유휴 상태이던 연결로 마을 입장 등 큰 데이터를 보냄 → 그러면: 혼잡 윈도우가 줄어 있어 여러 왕복에 나눠 전송 → 화면에서는: 입장 직후 주변 캐릭터와 NPC가 왕복 몇 번만큼 늦게 나타남(먼 서버일수록 눈에 띔)

증상: 입력 지연, 안 보임·유령 개체 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발

혼잡 제어로 전송량 급감 Congestion control backoff

TCP는 손실을 혼잡 신호로 보고 전송 속도를 30~50% 줄입니다. 와이파이 손실에도 똑같이 반응합니다.

왜: 보낼 양이 많을 때 와이파이나 회선에서 약간의 손실 발생 → 그러면: TCP가 전송 속도를 크게 줄이고 천천히 회복(리눅스·윈도우 기본인 CUBIC은 30% 줄임) → 화면에서는: 사람 많은 곳에서 업데이트가 밀려 몰아치기·입력 지연

증상: 몰아치기, 입력 지연 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발

RST 강제 종료로 마지막 데이터 유실 SO_LINGER, abrupt RST

서버가 연결을 급히 끊으면 마지막으로 보낸 안내나 저장 완료 신호가 사라집니다.

왜: 서버가 연결을 강제 종료(RST)로 닫음. SO_LINGER를 0초로 두거나, 받은 데이터를 다 읽지 않고 닫으면 생김 → 그러면: 아직 전송 중이던 킥 사유·마지막 데이터가 버려짐 → 화면에서는: 이유 없는 “알 수 없는 오류로 연결 종료”

증상: 접속 끊김 · 주 담당 게임개발팀·서버 개발

블로킹 I/O 구조 Blocking I/O model

소켓 하나를 기다리는 동안 스레드가 다른 일을 못 하는 구조에서는 사람이 늘수록 전체가 느려집니다.

왜: 연결마다 읽기·쓰기를 기다리는 방식 → 그러면: 한 연결의 지연이 같은 스레드의 다른 연결로 번짐 → 화면에서는: 동접이 늘수록 전체가 슬로우모션·입력 지연

증상: 슬로우모션, 입력 지연 · 주 담당 게임개발팀·서버 개발

SO_REUSEPORT 분배 쏠림 SO_REUSEPORT imbalance, stuck worker

같은 포트를 여러 프로세스가 나눠 받으면, 커널은 접속마다 주소 해시로 담당 프로세스를 정해 두고 바꾸지 않습니다. 담당 프로세스 하나가 멈추면 거기에 배정된 사람만 기다립니다.

왜: 게이트웨이·로그인 서버가 SO_REUSEPORT로 프로세스 여러 개를 띄움 → 그러면: 한 프로세스가 GC·과부하로 멈춰도 거기에 배정된 새 접속과 UDP 패킷은 다른 프로세스로 넘어가지 않음 → 화면에서는: 일부 사람만 접속 불가·멈춤. 프로세스 수가 바뀌는 재시작 때는 일부 UDP 세션이 끊김

증상: 접속 불가·무한 로딩, 멈춤, 접속 끊김 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

윈도우 UDP 소켓의 WSAECONNRESET 오류 WSAECONNRESET on a Windows UDP socket

윈도우 서버가 이미 떠난 클라이언트에게 UDP를 보내면 “포트 없음”(ICMP) 알림이 돌아옵니다. 그 알림 때문에 다음 수신 호출이 오류로 끝나는데 서버 코드가 이 오류를 소켓 자체의 고장으로 처리하면 그 소켓을 쓰는 모두가 영향을 받습니다.

왜: 막 나간 클라이언트의 주소로 계속 UDP를 보내 “포트 없음”(ICMP) 알림이 돌아옴 → 그러면: 윈도우가 그다음 수신 호출을 WSAECONNRESET(10054) 오류로 끝내고, 서버 코드가 수신을 멈추거나 소켓을 닫음 → 화면에서는: 그 소켓을 쓰던 모든 사람이 한꺼번에 멈춤·접속 끊김

증상: 접속 끊김, 멈춤 · 주 담당 게임개발팀·서버 개발

서버 게임 프로세스: 틱과 스레드

게임 로직을 실제로 계산하는 프로그램입니다. 이동, 전투, 몬스터 AI, 시야 계산, 브로드캐스트가 모두 “틱” 한 번 안에 끝나야 합니다. 사람이 한곳에 모일수록 시야 계산과 보낼 패킷은 인원의 제곱으로 늘어납니다.

서버는 정해진 틱 간격으로 게임 상태를 계산합니다. 20틱 서버라면 50ms마다 한 번, 그 안에 모든 플레이어의 입력을 적용하고 몬스터를 움직이고 누가 누구를 볼 수 있는지 계산하고(시야, AOI), 변한 내용을 볼 수 있는 모두에게 보냅니다. 이 50ms가 틱 예산입니다. 예산을 넘기면 다음 틱이 늦어집니다. 틱마다 게임 시간을 정해진 만큼만 진행하는 서버는 게임 속 시간 전체가 느리게 흐르고(슬로우모션), 실제로 흐른 시간만큼 한 번에 진행하는 서버는 속도는 지키는 대신 패킷이 드물어져 뚝뚝 끊기고 순간이동합니다. 어느 쪽이든 반응은 늦어집니다. 게임 스레드 하나가 서버(채널) 전체를 맡으면 그 서버의 모두가, 지역마다 스레드를 나눴다면 그 지역 사람들이 함께 겪습니다.

인원이 많을수록 틱 예산이 빠듯해집니다. 모두끼리 비교하면 100명은 약 1만 번, 1,000명은 약 100만 번을 매 틱 따져야 합니다. 그래서 서버는 맵을 격자(그리드)로 나눠 가까운 셀끼리만 비교합니다. 하지만 월드 보스, 공성전, 마을 광장 이벤트처럼 모두가 한 셀 근처에 몰리면 격자의 효과가 줄고 계산량과 보낼 데이터가 급격히 늘어납니다. 여기에 여러 스레드가 같은 데이터를 두고 기다리는 락, 틱 도중 DB 응답을 기다리는 동기 호출이 더해지면, 기다리는 동안 그 스레드가 맡은 모두가 함께 멈춥니다.

비유

서버의 틱은 지휘자의 박자입니다. 오케스트라 단원(플레이어)이 늘수록 한 박자 안에 챙겨야 할 악보가 늘어나고, 박자를 놓치면 곡 전체가 느려집니다. 누군가 악보 한 장을 찾으러 창고(DB)에 가 버리면 모두가 그 사람을 기다립니다.

이 층에서 렉을 만드는 원인

틱 예산 초과 Tick overrun

한 틱 안에 할 일이 예산을 넘으면 서버의 틱 주기가 늘어지고 그 지역 전체가 느리게 흐르거나 뚝뚝 끊깁니다.

왜: 한 틱(예: 50ms)에 처리할 일이 예산을 넘음 → 그러면: 1초에 20번 계산할 게임 상태를 8번만 계산 → 화면에서는: 그 지역 전체 슬로우모션(서버 설계에 따라 뚝뚝 끊김), 스킬 반응 늦음

증상: 슬로우모션, 입력 지연, 뚝뚝 끊김 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

시야(AOI) 계산 폭증 (N²) Area-of-interest explosion

누가 누구를 볼 수 있는지 모두끼리 비교하면, 인원이 10배가 될 때 계산은 100배가 됩니다.

왜: 모든 캐릭터끼리 거리를 비교하거나, 격자(그리드)로 나눠도 한 셀 근처에 수백 명이 몰림 → 그러면: 100명이면 약 1만 번, 1,000명이면 약 100만 번 비교 → 화면에서는: 월드 보스·공성전처럼 몰린 곳에서 틱이 폭증해 슬로우모션·뚝뚝 끊김

증상: 슬로우모션, 뚝뚝 끊김 · 주 담당 게임개발팀·서버 개발

브로드캐스트 폭증 Broadcast fan-out (N×N)

한 명의 움직임을 그를 보는 모두에게 보내면, 모인 인원의 제곱만큼 보낼 업데이트가 생깁니다.

왜: 한 명의 변화를 볼 수 있는 모두에게 전송 → 그러면: 1,000명이 서로를 보면 틱마다 100만 개 업데이트 → 화면에서는: 전송 대기열과 대역폭이 포화되어 지연·손실(입력 지연·몰아치기·순간이동)

증상: 입력 지연, 순간이동, 몰아치기 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

단일 스레드 지역 과부하(핫스팟) Single-threaded hot zone

지역마다 스레드 하나가 맡는 구조에서 한곳에 사람이 몰리면 그 코어 하나만 100%가 됩니다.

왜: 한 지역(채널)을 스레드 하나가 담당 → 그러면: 사람이 한곳에 몰리면 그 코어만 포화, 나머지 코어는 여유 → 화면에서는: 그 지역만 렉, 다른 지역은 멀쩡

증상: 슬로우모션, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

락 경합 Lock contention

여러 스레드가 같은 데이터를 쓰려고 락 하나를 기다리면, 스레드를 늘려도 한 번에 하나씩만 실행됩니다.

왜: 경매장·길드 창고처럼 공용 데이터를 여러 스레드가 동시에 사용 → 그러면: 락을 잡은 스레드가 끝날 때까지 나머지는 대기 → 화면에서는: 특정 기능만 느림, 심하면 전체 틱 지연

증상: 입력 지연, 멈춤 · 주 담당 게임개발팀·서버 개발

데드락 Deadlock

두 스레드가 서로 상대가 잡은 락을 기다리면 영원히 멈춥니다.

왜: 스레드 A는 락1을 잡고 락2를, B는 락2를 잡고 락1을 기다림 → 그러면: 둘 다 영원히 멈추고 관련 스레드도 줄줄이 멈춤 → 화면에서는: 서버 전체 정지, 워치독이 재시작하며 전원 접속 끊김

증상: 멈춤, 접속 끊김 · 주 담당 게임개발팀·서버 개발

게임 스레드의 동기 호출 Synchronous DB / file I/O on the game loop

틱 도중 DB 응답이나 파일 쓰기를 기다리면, 그 시간만큼 서버의 게임 진행 전체가 멈춥니다.

왜: 틱 안에서 DB 조회·저장, 로그 쓰기, 외부 API 호출을 기다림 → 그러면: DB가 100ms 걸리면 틱도 100ms 멈춤 → 화면에서는: DB·디스크가 느려질 때마다 필드 전체가 멈칫

증상: 멈춤, 뚝뚝 끊김 · 주 담당 게임개발팀·서버 개발

메시지 큐 적체 Mailbox / job queue backlog

요청이 처리 속도보다 빨리 들어와 대기열에 쌓이면, 뒤쪽 요청은 몇 초 뒤에야 처리되거나 버려집니다.

왜: 요청이 처리 속도보다 빨리 도착 → 그러면: 대기열이 길어지고 한도를 넘으면 버림 → 화면에서는: 스킬·거래 반응이 늦거나 씹힘

증상: 입력 지연, 씹힘·롤백 · 주 담당 게임개발팀·서버 개발

타이머 동시 발동 몰림 Synchronized timers

모든 몬스터 리스폰, 모든 버프 만료, 정각 보상이 같은 틱에 몰리면 그 틱만 수십 배 무거워집니다.

왜: 리스폰·만료·보상·자동 저장 타이머가 같은 시각에 맞춰짐 → 그러면: 그 한 틱에 평소의 수십 배 작업 → 화면에서는: 정해진 시각마다 한 번씩 멈칫

증상: 멈춤, 뚝뚝 끊김 · 주 담당 게임개발팀·서버 개발

길찾기 폭주 Pathfinding storms

수백 마리 몬스터가 동시에 플레이어를 쫓으며 경로를 계산하면 CPU를 크게 씁니다.

왜: 몰이 사냥, 대규모 스폰으로 몬스터가 동시에 추적 → 그러면: 몬스터마다 길찾기 계산 → 화면에서는: 그 사냥터만 슬로우모션

증상: 슬로우모션 · 주 담당 게임개발팀·서버 개발

직렬화·압축 비용 Serialization / compression cost

보낼 데이터를 바이트로 바꾸고 압축하는 데도 CPU가 들고 사람이 많으면 이 비용이 폭증합니다.

왜: 업데이트마다 구조체를 바이트로 변환·압축 → 그러면: 인원 제곱에 비례해 비용 증가 → 화면에서는: 전송이 늦어져 입력 지연

증상: 입력 지연 · 주 담당 게임개발팀·서버 개발

서버 크래시 Server process crash

처리하지 못한 오류로 서버 프로세스가 죽으면, 그 서버에 있던 모두의 접속이 동시에 끊깁니다.

왜: 없는 대상을 가리키는 오류(널 참조), 잘못된 데이터, 메모리 부족 등 치명적 오류 → 그러면: 서버(또는 존) 프로세스 종료 → 화면에서는: 모두 동시에 접속 끊김, 마지막 저장 이후 진행은 롤백될 수 있음

증상: 접속 끊김, 씹힘·롤백 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

스레드 풀 고갈 Thread pool starvation

작업을 처리할 워커 스레드가 모두 느린 작업에 묶이면 새 요청은 무작정 기다립니다.

왜: 워커 스레드들이 외부 API·DB 응답을 기다리며 묶임 → 그러면: 새 요청이 배정받을 스레드가 없음 → 화면에서는: 로그인·상점 등 특정 기능 무한 로딩

증상: 접속 불가·무한 로딩, 입력 지연, 멈춤 · 주 담당 게임개발팀·서버 개발

무한 루프·로직 폭주 Infinite loop / runaway logic

버그로 한 틱이 끝나지 않으면 서버가 멈추고 워치독이 강제로 재시작합니다.

왜: 잘못된 조건으로 반복이 끝나지 않거나 재귀 폭주 → 그러면: 틱이 끝나지 않아 서버 정지 → 화면에서는: 멈춤 후 전원 접속 끊김

증상: 멈춤, 접속 끊김 · 주 담당 게임개발팀·서버 개발

한 대상에 몰린 전투 (월드 보스) Hot entity / combat event fan-out

수백 명이 보스 하나를 동시에 때리면, 보스 한 마리의 계산이 한곳에 몰리고 타격 정보가 보는 모두에게 전송됩니다.

왜: 수백 명이 한 보스에게 스킬·버프·디버프를 쉬지 않고 사용 → 그러면: 보스의 체력·어그로 목록·디버프 계산이 한곳에 몰리고 타격마다 데미지 숫자·이펙트 패킷을 보는 모두에게 전송 → 화면에서는: 스킬이 늦게 들어가고 데미지 숫자가 몰아서 뜸, 보스 주변만 슬로우모션

증상: 입력 지연, 몰아치기, 슬로우모션 · 주 담당 게임개발팀·서버 개발

밀집 지역 진입 시 스폰 폭주 Spawn burst when entering a crowd

사람이 가득한 마을로 텔레포트하면, 서버는 새로 보이게 된 수백 명의 외형·장비·상태를 한꺼번에 보내야 합니다.

왜: 텔레포트·접속·채널 이동으로 붐비는 곳에 갑자기 나타남 → 그러면: 수백 명분의 전체 정보를 한 번에 만들어 보내고 내 PC도 한 번에 불러옴 → 화면에서는: 도착 직후 잠깐 멈춤, 캐릭터가 늦게 하나씩 나타나고 입력이 늦음

증상: 멈춤, 입력 지연, 몰아치기 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발

개체 누적 (정리되지 않은 아이템·소환물) Entity / timer buildup over uptime

사라져야 할 바닥 아이템, 소환물, 끝난 타이머가 정리되지 않고 쌓이면, 서버를 오래 켜 둘수록 매 틱 할 일이 늘어납니다.

왜: 바닥 아이템·소환물·만료된 타이머·빈 파티 정보가 제때 지워지지 않음 → 그러면: 틱마다 순회하는 목록이 날마다 길어짐 → 화면에서는: 점검 직후엔 멀쩡하다가 며칠 지나면 그 서버·지역만 점점 굼뜸

증상: 슬로우모션, 뚝뚝 끊김, 입력 지연 · 주 담당 게임개발팀·서버 개발

패치로 트래픽 패턴이 바뀜 Patch changes traffic pattern

새 콘텐츠·이펙트·동기화 항목이 패킷 크기와 빈도를 늘리면, 잘되던 서버가 패치 뒤부터 MTU·대역폭·패킷 수 한도에 걸립니다.

왜: 패치로 새 스킬 이펙트·동기화 항목·아이템 정보가 늘어 패킷이 커지거나 잦아짐 → 그러면: 큰 패킷은 MTU를 넘어 단편화되고 늘어난 양은 대역폭·클라우드 PPS 한도·송신 버퍼에 걸림 → 화면에서는: 패치 직후부터 붐비는 곳에서 순간이동·스킬 씹힘·입력 지연. 인프라는 바꾼 것이 없는데 손실이 늘어남

증상: 순간이동, 씹힘·롤백, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라, 인프라팀·네트워크 인프라

메모리

캐릭터·몬스터·아이템·맵처럼 서버가 기억하는 모든 것이 메모리에 올라 있습니다. 메모리 자체는 빠르지만 GC(쓰지 않는 메모리 회수)로 멈추거나, 조금씩 새어 나가거나(누수), 모자라서 스왑(메모리 일부를 디스크로 옮김)이 생기는 순간 렉이 됩니다.

Java·C#·Go처럼 메모리를 자동으로 관리하는 언어는 쓰고 버린 메모리를 가비지 컬렉터(GC)가 모아 회수합니다. GC 방식에 따라 모든 스레드를 잠깐 세우기도 합니다. 힙(프로그램이 실행 중에 할당받아 쓰는 메모리 영역) 전체를 한 번에 GC하면 살아 있는 데이터가 많을수록 오래 걸려 수백 ms에서 수 초에 이릅니다. ZGC 같은 최신 GC는 멈춤을 1ms 미만으로 줄이는 대신 CPU와 메모리를 더 씁니다. C++ 서버는 GC가 없지만 해제를 잊은 메모리가 쌓이는 누수와 빈 공간이 잘게 나뉘어 큰 덩어리를 못 쓰게 되는 단편화에 시달립니다. GC가 있어도 다 쓴 객체를 어딘가에서 계속 참조하고 있으면 똑같이 누수가 생깁니다.

메모리가 느려지는 또 다른 이유는 메모리 계층(CPU에서 얼마나 먼 저장 장치인가)입니다. CPU 바로 옆 캐시는 1ns, RAM은 100ns, 디스크로 내보낸 메모리(스왑)를 다시 읽으면 RAM의 1,000배가 넘게 걸립니다. 아래 “숫자 감각” 표에서 이 차이를 사람의 시간으로 늘려 보세요.

비유

메모리는 요리사의 작업대입니다. 손 닿는 곳(캐시)에 재료가 있으면 빠르고 냉장고(RAM)까지 가면 조금 느리고 작업대가 꽉 차서 재료를 창고(디스크, 스왑)에 두면 한 번 꺼낼 때마다 한참 걸립니다. 설거지(GC)하는 동안에는 요리를 멈춰야 합니다.

이 층에서 렉을 만드는 원인

서버 GC 전체 멈춤 Stop-the-world GC pause

Java·C# 서버가 가비지를 수집하려고 모든 스레드를 멈추는 동안(stop-the-world) 서버 전체가 멈춥니다.

왜: 힙이 차서 GC 시작 → 그러면: 모든 게임 스레드를 멈추고 수집(살아 있는 데이터가 많을수록 오래) → 화면에서는: 서버의 모두가 동시에 멈췄다가 몰아치기

증상: 멈춤, 몰아치기 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

스크립트 엔진의 GC 멈춤 Scripting VM GC (Lua, etc.)

C++ 서버라도 퀘스트·AI·스킬을 Lua 같은 스크립트로 돌리면, 스크립트 엔진의 GC가 도는 동안 그 존이 멈춥니다.

왜: 존마다 스크립트 엔진이 퀘스트·AI·이벤트를 실행하며 임시 객체를 대량 생성 → 그러면: 스크립트 엔진의 GC가 한 번에 많이 수집하면 그 존의 틱이 멈춤 → 화면에서는: 특정 존·특정 이벤트 중에만 주기적으로 멈칫

증상: 뚝뚝 끊김, 멈춤 · 주 담당 게임개발팀·서버 개발

할당 폭주 Allocation storms

이벤트 중 임시 객체를 대량으로 만들면 GC가 평소보다 훨씬 자주 돕니다.

왜: 아이템 드롭·전투 로그·이벤트 보상으로 임시 객체 폭증 → 그러면: GC가 몇 배 자주 돌고 미처 버려지지 않은 객체가 Old 영역으로 넘어가 Full GC도 앞당겨짐 → 화면에서는: 이벤트 때만 주기적으로 멈칫

증상: 뚝뚝 끊김, 멈춤 · 주 담당 게임개발팀·서버 개발

메모리 누수 Memory leak

해제되지 않는 메모리가 조금씩 쌓이면 며칠 뒤 GC 폭주·스왑·강제 종료가 일어납니다.

왜: 접속 종료한 캐릭터 정보·이벤트 핸들러가 해제되지 않음 → 그러면: 며칠에 걸쳐 여유 메모리가 줄어듦 → 화면에서는: 점검 직후엔 멀쩡, 날이 갈수록 렉, 결국 서버 다운

증상: 슬로우모션, 멈춤, 접속 끊김 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

GC 스래싱 (힙 여유 부족) GC thrashing (heap nearly full)

살아 있는 데이터가 힙 한도에 가까워지면, GC가 돌아도 회수할 것이 거의 없어 GC가 쉬지 않고 반복됩니다.

왜: 이벤트 인원 증가나 누수로 살아 있는 데이터가 힙 한도 가까이 참 → 그러면: GC가 조금밖에 회수하지 못해 곧바로 다시 Full GC, CPU 대부분을 GC가 씀 → 화면에서는: 서버 전체가 몇 분간 슬로우모션·멈춤을 반복하다 메모리 부족으로 종료

증상: 슬로우모션, 멈춤, 접속 끊김 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

스왑 Swapping

메모리가 모자라 OS가 일부를 디스크로 내보내면, 그 메모리를 쓸 때마다 1,000배 넘게 느린 디스크를 기다립니다.

왜: 사용 메모리가 실제 램을 넘음 → 그러면: OS가 일부를 디스크로 내보내고 필요할 때 다시 읽음 → 화면에서는: 틱이 수백 ms로 폭증해 서버의 모든 유저가 슬로우모션·멈춤

증상: 슬로우모션, 멈춤 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발

캐시 미스 CPU cache misses

데이터가 메모리 여기저기 흩어져 있으면 CPU가 매번 느린 RAM까지 가서 기다립니다.

왜: 객체가 포인터로 흩어져 있고 순서 없이 접근 → 그러면: CPU 캐시에 없어서 매번 RAM에서 읽음(100배 안팎 느림) → 화면에서는: 같은 일을 해도 틱 비용이 몇 배, 심하면 슬로우모션

증상: 슬로우모션 · 주 담당 게임개발팀·서버 개발

메모리 단편화 Heap fragmentation

할당과 해제를 반복해 빈 공간이 잘게 쪼개지면, 실제로 쓰는 양보다 훨씬 많은 메모리를 점유합니다.

왜: 크기가 제각각인 메모리를 여러 스레드가 오랫동안 할당·해제 → 그러면: 빈 공간이 잘게 흩어져 OS에 돌려주지 못하고 사용량이 누수처럼 계속 늘어남 → 화면에서는: 오래 켤수록 스왑·메모리 부족으로 느려지다 강제 종료

증상: 슬로우모션, 접속 끊김 · 주 담당 게임개발팀·서버 개발

NUMA 원격 메모리 Remote NUMA access

CPU가 두 개인 서버에서 반대편 CPU에 붙은 메모리를 쓰면 접근이 느려집니다.

왜: 스레드와 메모리가 서로 다른 CPU 소켓에 배치 → 그러면: 메모리 접근이 느려짐(장비에 따라 1.5~2배) → 화면에서는: 같은 사양인데 프로세스마다 성능 차이

증상: 슬로우모션 · 주 담당 인프라팀·서버 인프라

디스크

로그, 캐릭터 저장, 맵 데이터, DB 파일이 모두 디스크에 있습니다. 디스크는 메모리보다 수백 배(SSD)에서 10만 배(HDD)까지 느리기 때문에, 게임 서버가 디스크를 기다리는 구조라면 디스크가 바빠지는 순간 게임도 같이 멈춥니다.

디스크의 성능은 “1초에 몇 번 읽고 쓸 수 있나”(IOPS)로 잽니다. 오래된 HDD는 150번 남짓, SSD는 수만~수십만 번입니다. 클라우드 디스크는 돈을 낸 만큼 한도가 정해집니다(AWS 기본 gp3는 3,000번). 일부 클라우드 디스크와 작은 서버 사양은 평소 속도에 더해 잠깐 더 높은 성능을 낼 수 있는 버스트 크레딧을 줍니다. 바쁜 시간이 길어지면 크레딧이 바닥나 속도가 갑자기 떨어집니다. “매일 저녁 몇 시간이 지나면 렉”이라는 제보가 이 모양입니다.

디스크가 렉을 만드는지는 누가 기다리느냐에 달렸습니다. 보통의 파일 쓰기는 OS가 메모리에 먼저 받아 두고 나중에 디스크로 내려보내서 대개 곧바로 끝납니다. 하지만 “디스크에 실제로 기록될 때까지” 기다리라고 하거나(fsync) OS가 메모리에 받아 둘 수 있는 한도가 차면 쓰기가 디스크를 기다립니다. 이때 게임 스레드가 직접 기다리면(동기), 디스크가 100ms 밀릴 때 틱도 100ms 멈춥니다. 쓰기를 별도 스레드에 넘기면(비동기) 게임은 멈추지 않지만 서버가 갑자기 죽으면 아직 못 쓴 내용이 사라질 수 있습니다(씹힘·롤백).

비유

디스크는 창고, IOPS는 창고 문 개수입니다. 문이 적으면 물건을 넣고 빼는 사람이 줄을 섭니다. 버스트 크레딧은 잠깐 전력 질주할 수 있는 체력이라, 다 쓰면 걷는 속도로 돌아갑니다.

이 층에서 렉을 만드는 원인

동기 로그 쓰기 Synchronous logging

게임 스레드가 로그 한 줄마다 디스크 완료를 기다리면, 디스크가 바쁠 때 게임 진행도 같이 멈춥니다.

왜: 전투·거래 로그를 게임 스레드에서 바로 파일에 씀 → 그러면: 확실한 저장(fsync)을 요구하거나 OS의 쓰기 버퍼(페이지 캐시)가 한도에 차면, 디스크가 바쁠 때 쓰기 한 번이 수십 ms → 화면에서는: 로그 많은 전투에서 멈칫

증상: 뚝뚝 끊김, 멈춤 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

fsync 폭주 fsync storms

데이터를 “확실히” 디스크에 쓰도록 요청하면 디스크에 따라 한 번에 0.1ms~수십 ms가 걸리고, 몰리면 대기열이 길어집니다.

왜: 정기 저장·로그아웃 러시로 확실한 쓰기 요청이 몰림 → 그러면: 디스크 대기열이 길어짐 → 화면에서는: 저장 시각마다 렉, 로그아웃·채널 이동 지연

증상: 뚝뚝 끊김, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라, 인프라팀·DB 인프라

클라우드 디스크 버스트 크레딧 소진 Burst credit depletion

일부 클라우드 디스크와 작은 서버 사양은 잠깐 기준보다 빠르게 쓸 수 있는 버스트 크레딧이 있어서, 바쁜 시간이 길어져 크레딧이 바닥나면 속도가 갑자기 떨어집니다.

왜: 기준 성능 이상으로 오래 사용 → 그러면: 버스트 크레딧이 바닥나 기준 성능으로 급락 → 화면에서는: 매일 저녁 몇 시간 지나서부터 렉 시작

증상: 뚝뚝 끊김, 슬로우모션, 입력 지연 · 주 담당 인프라팀·서버 인프라 · 함께 인프라팀·DB 인프라

IOPS 한도·대기열 포화 IOPS limit / queue saturation

디스크가 1초에 처리할 수 있는 요청 수를 넘으면 대기열이 길어져 지연이 폭증합니다.

왜: 읽기·쓰기 요청이 디스크 처리 능력에 근접 → 그러면: 대기열이 길어짐(대개 이용률 90% 이상에서 폭증) → 화면에서는: 저장·로딩 지연, 동기 호출이면 멈춤

증상: 입력 지연, 멈춤 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발, 인프라팀·DB 인프라

디스크 가득 참 Disk full

로그와 덤프가 쌓여 디스크가 가득 차면 쓰기가 실패하고 대비가 없으면 서버가 죽습니다.

왜: 로그·덤프·임시 파일이 쌓여 100% → 그러면: 쓰기 실패. 오류 처리가 없으면 크래시, 있으면 저장 실패 → 화면에서는: 접속 끊김, 진행 롤백

증상: 접속 끊김, 씹힘·롤백 · 주 담당 인프라팀·서버 인프라 · 함께 인프라팀·DB 인프라, 게임개발팀·서버 개발

백업·압축·검사 작업 Backup / compression / scans

새벽 백업, 로그 압축, 보안 검사가 디스크를 독점하면 게임 서버의 읽기·쓰기가 밀립니다.

왜: 예약된 백업·압축 작업 시작 → 그러면: 디스크 대역폭과 IOPS를 대부분 차지 → 화면에서는: 매일 같은 시각 렉

증상: 뚝뚝 끊김, 입력 지연 · 주 담당 인프라팀·서버 인프라 · 함께 인프라팀·DB 인프라

서버의 지연 로딩 Lazy loading on the server

서버가 던전·맵 데이터를 처음 요청받을 때 디스크에서 읽으면, 그 틱 동안 모두가 멈춥니다.

왜: 누군가 처음으로 던전·지역에 입장 → 그러면: 서버가 게임 스레드에서 데이터를 디스크에서 읽음 → 화면에서는: 그 서버의 모두가 잠깐 멈춤

증상: 멈춤 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

코어 덤프 기록 Core dump writing

서버가 죽을 때 수 GB 메모리를 디스크에 기록하느라 재시작이 몇 분씩 늦어지기도 합니다.

왜: 서버 크래시로 메모리 전체를 파일로 기록 → 그러면: 수 GB를 쓰는 동안 재시작 불가 → 화면에서는: 서버가 죽어 접속이 끊긴 뒤 한참 동안 접속 불가

증상: 접속 불가·무한 로딩 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발

HDD 탐색 지연 HDD seek latency

HDD는 헤드가 플래터 위를 움직여야(탐색, seek) 해서 흩어진 데이터를 읽고 쓰는 데 한 번에 10ms 가까이 걸립니다.

왜: 오래된 서버나 저가 스토리지에서 HDD 사용 → 그러면: 흩어진 읽기·쓰기마다 약 10ms → 화면에서는: 전반적인 저장·로딩 지연

증상: 입력 지연 · 주 담당 인프라팀·서버 인프라 · 함께 인프라팀·DB 인프라, 게임개발팀·서버 개발

데이터베이스

캐릭터, 아이템, 재화, 거래 기록처럼 절대 잃으면 안 되는 것들이 들어 있는 곳입니다. DB가 느려지면 전투는 멀쩡한데 아이템이 늦게 들어오고 거래가 실패하고 로그인이 끝나지 않습니다. 게임 서버가 DB를 기다리는 구조라면 필드 전체가 멈춥니다.

게임 서버는 DB와 미리 몇 개의 연결(커넥션 풀)을 맺어 두고 번갈아 씁니다. 쿼리(DB에 보내는 요청) 하나가 오래 걸리면 그 커넥션이 계속 사용 중이 되고, 풀의 커넥션이 모두 사용 중이면 나머지 요청은 대기열에서 기다립니다. 쿼리가 느려지는 흔한 이유는 두 가지입니다. 인덱스(책의 색인)가 없어 테이블 전체를 읽는 경우(풀 스캔)와 여러 요청이 같은 행을 동시에 고치려다 잠금을 기다리는 경우입니다.

DB는 믿을 수 있게, 또 많은 요청을 받으려고 여러 장치를 씁니다. 읽기를 나눠 받는 복제본, 장애 시 넘어가는 예비 DB, 변경분을 주기적으로 디스크에 몰아 쓰는 체크포인트. 체크포인트가 몰리면 잠깐 느려집니다. 복제본이 늦으면 “방금 산 아이템이 안 보여요”, 복제가 늦은 채로 예비 DB로 넘어가면 “접속하니 조금 전 상태로 돌아갔어요” 같은 씹힘·롤백 증상이 생깁니다. 게임 서버가 캐릭터를 몇 분에 한 번만 저장한다면, 서버가 죽을 때 “10분 전으로 돌아갔어요”가 됩니다.

비유

DB는 은행 창구입니다. 창구 수(커넥션 풀)가 정해져 있고 요청 하나가 장부 전체를 뒤지는 일(풀 스캔)을 하면 뒤의 요청이 모두 기다립니다. 모두가 같은 금고(핫 로우)를 열려고 하면 한 명씩만 들어갈 수 있습니다.

이 층에서 렉을 만드는 원인

인덱스 없는 쿼리 Missing index / full table scan

인덱스 없이 조건에 맞는 행을 찾으려면 테이블 전체를 읽어야 합니다(풀 스캔).

왜: 새 기능 배포로 인덱스가 없는 조건 검색 추가 → 그러면: 수백만 행을 모두 스캔해 쿼리 하나에 수백 ms~수 초 → 화면에서는: 우편함·거래 기록 로딩 지연, 커넥션이 묶여 다른 요청까지 대기

증상: 입력 지연, 접속 불가·무한 로딩 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

핫 로우 잠금 경합 Hot row lock contention

모두가 같은 행(길드 창고, 경매장 인기 아이템, 서버 전체 카운터)을 고치려 하면 한 명씩만 잠금을 얻습니다.

왜: 이벤트·인기 아이템으로 같은 행에 수정이 몰림 → 그러면: 잠금을 얻을 때까지 요청이 대기 → 화면에서는: 거래 실패, “잠시 후 다시 시도”, 타임아웃

증상: 씹힘·롤백, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

DB 데드락 Database deadlock

두 트랜잭션(한 묶음으로 처리되는 DB 작업)이 서로 상대가 잠근 행을 기다리면 DB가 한쪽을 강제로 취소합니다.

왜: 거래 A는 아이템→재화, B는 재화→아이템 순서로 잠금 → 그러면: DB가 데드락을 감지해 한쪽을 롤백 → 화면에서는: 거래·제작이 가끔 실패, 아이템이 되돌아감

증상: 씹힘·롤백, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

커넥션 풀 고갈 Connection pool exhaustion

DB와 맺어 둔 연결 수가 정해져 있어서 느린 쿼리가 연결을 점유하면 나머지는 대기합니다.

왜: 느린 쿼리나 요청 폭주로 모든 연결이 사용 중 → 그러면: 새 요청은 연결이 날 때까지 대기 → 화면에서는: 로그인 무한 로딩, 저장 지연, 타임아웃

증상: 접속 불가·무한 로딩, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

복제 지연 Replication lag

쓰기는 주 DB에, 읽기는 복제본에서 하는데 복제본이 늦게 따라오면 방금 쓴 내용이 안 보입니다.

왜: 주 DB에 쓰기가 몰려 복제본이 수 초 뒤처짐 → 그러면: 방금 저장한 내용을 복제본에서 읽으면 아직 없음 → 화면에서는: 방금 산 아이템이 안 보임, 거래소 가격이 옛날 값, 중복 지급 버그

증상: 씹힘·롤백 · 주 담당 인프라팀·DB 인프라 · 함께 게임개발팀·서버 개발

체크포인트·로그 플러시 Checkpoint / log flush stalls

DB가 메모리의 변경분을 주기적으로 디스크에 몰아서 쓰는 순간 쿼리가 느려집니다.

왜: 변경분이 쌓여 주기적으로 디스크에 기록 → 그러면: 그 순간 디스크가 바빠져 쿼리 지연 → 화면에서는: 주기적으로 저장·로딩이 느려짐

증상: 입력 지연, 뚝뚝 끊김 · 주 담당 인프라팀·DB 인프라

콜드 캐시 (재시작 직후) Cold buffer pool after restart

DB를 재시작하면 메모리 캐시가 비어 있어서 한동안 조회하는 데이터를 모두 디스크에서 읽습니다.

왜: 점검으로 DB 재시작 → 그러면: 자주 쓰던 데이터가 메모리에 없어 디스크에서 읽음 → 화면에서는: 점검 직후 한동안 로그인·로딩이 느림

증상: 접속 불가·무한 로딩, 입력 지연 · 주 담당 인프라팀·DB 인프라 · 함께 게임개발팀·서버 개발

로그인 폭주와 N+1 쿼리 Login storm, N+1 queries

캐릭터 하나를 불러올 때 수십 번 따로 조회하면, 수만 명 동시 로그인이 쿼리 수백만 개가 됩니다.

왜: 캐릭터 로딩 때 아이템·스킬·퀘스트를 따로따로 조회 → 그러면: 점검 직후 동시 로그인으로 쿼리 폭증 → 화면에서는: 로그인 무한 로딩, 게임 중인 사람의 저장까지 밀림

증상: 접속 불가·무한 로딩, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

대량 배치 작업 Batch jobs during service

랭킹 집계, 우편 일괄 발송, 오래된 데이터 정리를 운영 중에 돌리면 잠금과 디스크를 차지합니다.

왜: 운영 시간에 대량 작업 실행 → 그러면: 넓은 범위 잠금, 디스크·CPU 점유 → 화면에서는: 특정 시간대 거래·저장 실패, 로딩 지연

증상: 입력 지연, 씹힘·롤백 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

DB 장애 전환 Database failover

주 DB가 죽어 예비 DB로 전환되는 동안 쓰기가 안 되고 복제되지 못한 마지막 데이터는 사라질 수 있습니다.

왜: 주 DB 장애로 예비 DB가 승격 → 그러면: 전환 중 수 초~몇 분 쓰기 불가, 비동기 복제라면 미복제 데이터 유실 가능 → 화면에서는: 잠깐 모든 저장 실패, 아이템·경험치 롤백

증상: 씹힘·롤백, 멈춤, 접속 끊김, 접속 불가·무한 로딩 · 주 담당 인프라팀·DB 인프라 · 함께 게임개발팀·서버 개발

긴 저장 주기로 인한 진행 유실 Periodic save window

부하를 줄이려 몇 분에 한 번만 저장하면, 그 사이 서버가 죽을 때 진행이 사라집니다.

왜: 캐릭터 상태를 몇 분마다 한 번 저장 → 그러면: 그 사이 서버 크래시·장애 발생 → 화면에서는: 다시 접속하니 몇 분 전 상태(롤백)

증상: 씹힘·롤백 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

캐시 스탬피드 Cache stampede / thundering herd

인기 데이터의 캐시가 동시에 만료되면 수천 개 요청이 한꺼번에 DB로 몰립니다.

왜: Redis 등에 저장된 인기 데이터가 동시에 만료 → 그러면: 같은 데이터를 다시 만들려는 요청이 DB로 한꺼번에 몰림 → 화면에서는: DB 과부하로 여러 기능이 줄줄이 느려지거나 멈춤

증상: 입력 지연, 멈춤, 접속 불가·무한 로딩 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

오래 열린 트랜잭션 Long-running transaction / MVCC purge lag

트랜잭션 하나가 오래 열려 있으면 잠금을 계속 잡고 있고 DB가 옛 버전 데이터를 정리(purge)하지 못해 전체가 점점 느려집니다.

왜: 트랜잭션을 연 채 다른 서버 응답을 기다리거나, 운영 중 주 DB에서 긴 집계 쿼리 실행 → 그러면: 잡은 잠금이 풀리지 않고 정리해야 할 옛 버전 데이터가 계속 쌓임 → 화면에서는: 그 행을 쓰는 기능 타임아웃, 몇 시간에 걸쳐 저장·조회가 전반적으로 느려짐

증상: 입력 지연, 씹힘·롤백 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

Redis 느린 명령 Redis blocking commands (single-threaded)

Redis는 명령을 한 번에 하나씩 처리해서 느린 명령 하나가 그 뒤의 모든 요청을 막습니다.

왜: 운영 중 KEYS로 전체 검색, 원소 수백만 개짜리 랭킹·목록을 통째로 읽거나 지움 → 그러면: 그 명령이 끝날 때까지 다른 모든 요청이 대기(수십 ms~수 초) → 화면에서는: 세션·랭킹·캐시를 쓰는 기능이 동시에 멈칫, 로그인 지연

증상: 멈춤, 입력 지연, 접속 불가·무한 로딩 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·DB 인프라

실행 계획 변경으로 인한 쿼리 지연 Query plan regression (stats, parameter sniffing)

코드는 그대로인데 DB가 같은 쿼리를 처리하는 방법(실행 계획)을 바꾸면, 어제 2ms였던 쿼리가 오늘 수백 ms가 됩니다.

왜: 통계 자동 갱신, DB 재시작, 데이터 분포 변화로 DB가 실행 계획을 새로 세움 → 그러면: 인덱스를 안 타는 계획이 골라져 같은 쿼리가 수십~수백 배 느려지고 커넥션이 묶임 → 화면에서는: 배포도 없었는데 특정 기능 로딩이 갑자기 느려지고 다른 요청까지 대기

증상: 입력 지연, 접속 불가·무한 로딩 · 주 담당 인프라팀·DB 인프라 · 함께 게임개발팀·서버 개발

운영 중 스키마 변경(DDL) 잠금 Schema change lock (DDL / metadata lock)

서비스 중에 테이블에 컬럼이나 인덱스를 추가하면, 잠깐 필요한 잠금 하나 때문에 그 테이블을 쓰는 모든 요청이 대기할 수 있습니다.

왜: 핫픽스로 운영 중인 테이블에 컬럼·인덱스 추가 → 그러면: 스키마 변경이 앞서 열린 긴 트랜잭션을 기다리고 뒤에 오는 모든 요청은 그 스키마 변경을 기다림 → 화면에서는: 그 테이블을 쓰는 기능(인벤토리, 우편 등)이 통째로 멈추고 타임아웃

증상: 입력 지연, 씹힘·롤백, 접속 불가·무한 로딩 · 주 담당 인프라팀·DB 인프라 · 함께 게임개발팀·서버 개발

서버 구성과 운영

요즘 MMO는 대개 로그인, 게이트웨이, 필드, 던전, 채팅, 파티, 경매장, 캐시, DB 서버가 서로 호출하며 돌아가는 구조입니다. 한 곳에 장애가 나면 연결된 곳으로 번지고 배포·확장·점검 같은 운영 작업도 렉을 만듭니다.

서버를 나누면 한 곳의 장애가 전체로 번지지 않게 막을 수 있지만 대신 호출 체인(서버가 서버를 차례로 부르는 연결)이 생깁니다. 게임 서버가 경매장 서버를 부르고 경매장 서버가 캐시와 DB를 부르는 식입니다. 체인 끝의 서버가 느려지면 앞쪽 서버들은 응답을 기다리며 스레드와 커넥션을 계속 점유하고, 결국 상관없어 보이는 기능까지 멈춥니다. 이를 연쇄 장애라고 하며 타임아웃과 서킷 브레이커(실패가 이어지는 호출을 잠시 차단하는 장치)로 번지는 것을 막습니다.

운영 작업도 렉의 원인입니다. 업데이트 배포 중 재시작, 사람이 몰릴 때 서버를 자동으로 늘리는 데 걸리는 몇 분, 존 이동 때 캐릭터를 다른 서버로 옮기는 과정, 봇과 매크로가 만드는 보이지 않는 부하가 모두 플레이어에게는 “렉”으로 보입니다.

비유

서버 구성은 여러 부서가 결재를 주고받는 회사입니다. 결재 라인 끝의 부서(DB) 한 곳이 느려지면 앞 부서들은 서류를 들고 줄을 서고, 결국 회사 전체 업무가 멈춥니다. 타임아웃은 “10분 넘게 답이 없으면 일단 반려”하는 규칙이고 차단기는 “반려가 계속되면 한동안 그 부서로는 서류를 보내지 않고 바로 돌려보내는” 규칙입니다.

이 층에서 렉을 만드는 원인

게이트웨이·프록시 경유 Gateway / proxy hop

클라이언트와 게임 서버 사이에 중간 서버를 두면, 한 번 거칠 때마다 처리 시간이 붙고 그 서버가 단일 장애 지점이 됩니다.

왜: 클라이언트 ↔ 게이트웨이 ↔ 게임 서버 구조 → 그러면: 중간 서버의 처리·대기 추가, 과부하 시 모두에게 영향 → 화면에서는: 전체 핑 상승, 게이트웨이 장애 시 그곳을 거치는 사용자 전원 접속 끊김

증상: 입력 지연, 접속 끊김 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라, 게임개발팀·클라이언트 개발

존 이동 (서버 간 이관) Zone / server handoff

다른 지역·던전에 들어갈 때 캐릭터 정보를 다른 서버로 넘기는 과정에서 지연과 실패가 생깁니다.

왜: 던전 입장, 대륙 이동으로 담당 서버가 바뀜 → 그러면: 저장 → 전달 → 불러오기, 대상 서버가 붐비거나 빈 던전 인스턴스가 없으면 대기 → 화면에서는: 긴 로딩, 입장 실패, 이동 중 접속 끊김

증상: 접속 불가·무한 로딩, 멈춤, 접속 끊김, 고무줄 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

연쇄 장애 Cascading failure

한 서비스가 느려지면 그걸 부르는 서버들이 응답을 기다리며 묶이고 상관없는 기능까지 멈춥니다.

왜: DB·인증 같은 한 서비스가 느려짐 → 그러면: 호출하는 서버들의 스레드와 연결이 응답을 기다리며 묶이고 실패한 요청의 재시도가 부하를 더함 → 화면에서는: 상관없어 보이는 기능까지 전부 느려지거나 멈춤

증상: 멈춤, 입력 지연, 접속 불가·무한 로딩 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·네트워크 인프라

부가 서버 장애 Auxiliary service outage

채팅·파티·경매장처럼 게임 서버와 따로 도는 서버에 장애가 나면 그 기능만 동작하지 않습니다.

왜: 기능 전용 서버가 느려지거나 죽음 → 그러면: 해당 기능 요청만 응답 없음 → 화면에서는: 채팅 안 됨, 파티 초대 무반응, 거래소 무한 로딩(전투는 정상)

증상: 씹힘·롤백, 접속 불가·무한 로딩 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

배포·재시작 Deploy / rolling restart

업데이트하려고 서버를 재시작할 때 연결을 옮기지 않으면 그 서버에 있던 사람들의 접속이 끊기고, 종료 직전 저장과 재접속이 한꺼번에 몰립니다.

왜: 핫픽스 배포로 서버를 순서대로 재시작 → 그러면: 연결을 다른 서버로 옮기지 않고 종료, 그 서버에 있던 모든 유저의 저장이 DB에 몰림 → 화면에서는: 공지 없는 접속 끊김, 재접속 폭주

증상: 접속 끊김, 접속 불가·무한 로딩, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

오토스케일링 지연 Autoscaling lag

사람이 몰리면 서버를 자동으로 늘리지만 준비에 몇 분이 걸리고 그동안 기존 서버가 과부하입니다.

왜: 이벤트 시작으로 접속 급증 → 그러면: 새 서버가 켜지고 준비되기까지 수 분 → 화면에서는: 이벤트 시작 직후 몇 분간 슬로우모션·접속 불가

증상: 슬로우모션, 접속 불가·무한 로딩 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발

로그·모니터링 과부하 Logging / monitoring overhead

장애가 나면 로그가 폭증하고 로그를 동기로 넘기는 서버는 로그 때문에 더 느려집니다.

왜: 오류가 나며 로그·지표 전송량 폭증 → 그러면: 로그 수집기가 밀리고 동기 전송하는 서버는 대기 → 화면에서는: 장애 때 뚝뚝 끊김·멈춤이 로그 때문에 더 심해짐

증상: 뚝뚝 끊김, 멈춤 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·서버 인프라

서버 간 시계 차이 Clock skew between servers

서버마다 시계가 조금씩 다르면 쿨타임·버프·이벤트 시작 판정이 서버마다 어긋납니다.

왜: 시간 동기화가 멈춘 서버의 시계가 다른 서버와 수백 ms~수 초 벌어짐 → 그러면: 버프 끝나는 시각 같은 절대 시각을 서버 사이에 넘기면 판정이 어긋남 → 화면에서는: 이동하니 버프가 사라지거나 쿨타임이 다시 참

증상: 씹힘·롤백 · 주 담당 인프라팀·서버 인프라 · 함께 게임개발팀·서버 개발

매크로·봇 과다 Bots and macros

봇은 사람보다 훨씬 자주 요청을 보내 서버 처리량을 잠식합니다.

왜: 사냥·이동·거래를 쉬지 않고 반복하는 봇 대량 접속 → 그러면: 서버 처리량과 DB 부하 증가 → 화면에서는: 특정 사냥터나 서버 전체가 느려짐(슬로우모션·입력 지연)

증상: 슬로우모션, 입력 지연 · 주 담당 게임개발팀·서버 개발 · 함께 인프라팀·네트워크 인프라

외부 서비스 의존 External dependencies (auth, billing, platform)

플랫폼 로그인, 결제, 본인 인증 같은 외부 서비스가 느리거나 멈추면 그 단계에서 막힙니다.

왜: 외부 인증·결제 서비스 장애나 지연 → 그러면: 해당 단계에서 응답을 기다림 → 화면에서는: 로그인 불가, 결제 실패. 이미 게임 중인 사람은 멀쩡

증상: 접속 불가·무한 로딩, 씹힘·롤백 · 주 담당 외부·외부 · 함께 게임개발팀·서버 개발

매치메이킹·리전 배정 오류 Wrong region assignment (matchmaking / GeoDNS)

가까운 리전 대신 먼 리전의 서버에 배정되면, 회선이 멀쩡해도 그 유저만 핑이 늘 높습니다.

왜: GeoIP 데이터 오류, VPN, 파티원 평균 핑으로 파티 전체를 배정, 인원이 모자랄 때 먼 리전까지 넓히는 규칙, DNS 리졸버 위치 기준 배정 → 그러면: 가까운 리전이 있는데도 바다 건너 리전의 서버에 접속 → 화면에서는: 여러 리전에 서버를 둔 게임에서 나만(또는 우리 파티만) 핑이 늘 높고 입력 지연·고무줄·스킬 씹힘

증상: 입력 지연, 고무줄, 씹힘·롤백 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발, 인프라팀·네트워크 인프라, 외부·외부

TLS 인증서 만료·설정 오류 TLS certificate expiry / misconfiguration

로그인·API·패치 서버의 인증서가 만료되거나 중간 인증서가 빠지면, 그 순간부터 새로 연결하는 클라이언트의 TLS 연결이 실패합니다.

왜: 인증서 유효 기간이 지났거나, 서버가 중간 인증서를 빼고 보내거나, 유저 기기의 날짜·시간이 틀림 → 그러면: 클라이언트가 인증서 검증에 실패해 TLS 연결을 끊음 → 화면에서는: 로그인·패치 단계에서 접속 불가·무한 로딩, 상점 같은 HTTPS 기능만 실패. 이미 접속해 있던 사람은 대개 멀쩡

증상: 접속 불가·무한 로딩, 씹힘·롤백 · 주 담당 인프라팀·네트워크 인프라 · 함께 인프라팀·서버 인프라, 게임개발팀·클라이언트 개발

로그인 대기열 상한·재접속 유예 부족 Login queue cap / no reconnect grace

출시·점검 직후 접속이 몰리면 로그인 대기열이 상한에 닿아 새 대기를 거절하고, 기다리던 유저는 잠깐 끊긴 사이 자리를 잃어 맨 뒤로 돌아갑니다.

왜: 로그인 서버가 한 번에 받을 수 있는 인원보다 접속하려는 사람이 많아 대기열을 두고, 너무 길어지면 서버를 지키려고 새 대기를 거절함 → 그러면: 대기열이 길수록 기다리는 시간이 늘고 그동안 와이파이·모바일망이 잠깐만 끊겨도 대기 자리를 잃음 → 화면에서는: 접속 불가·무한 로딩, 대기 중 오류와 함께 게임 종료, 다시 맨 뒤에서 기다림

증상: 접속 불가·무한 로딩, 접속 끊김 · 주 담당 게임개발팀·서버 개발 · 함께 게임개발팀·클라이언트 개발, 인프라팀·서버 인프라

T1도구

진단 도우미

렉 제보를 받았을 때 “누가, 언제, 어떤 모양으로” 세 가지만 골라 보세요. 이 백서에 실린 원인 중 가장 잘 맞는 후보를 점수 순으로 보여 줍니다. 확정 진단은 아니지만 어느 팀에 먼저 물어볼지 정하는 데 충분합니다.

T2도구

관측으로 판정하기

제보나 경보가 오면 범위 → 시점 → 계층 순서로 좁힙니다. 이상이 어디에 몰렸는지가 담당을 가장 크게 가르고 무엇과 겹쳤는지가 원인을 좁히며 어느 계층의 지표가 비정상인지로 확인합니다. 원인 카드마다 있는 “그래프에서는”과 “확인 방법”을 함께 쓰면, 그래프 모양으로 후보를 고르고 확인할 곳을 바로 찾을 수 있습니다.

판정 흐름

1 범위

이상이 어디에 몰렸나

  • 특정 국가·통신사(ASN) → 인프라팀네트워크 외부통신사
  • 특정 서버·채널·존 → 호스트 지표가 정상이면 게임개발팀서버, 비정상이면 인프라팀서버 장비·OS
  • 특정 OS·기기·빌드 → 게임개발팀클라이언트
  • 한 명·한 집 → 외부유저 환경 (여러 명이 같은 모양이면 게임개발팀클라이언트)
  • 전체가 동시에 → 공용 자원(DB·로드밸런서·게이트웨이) 또는 방금 나간 배포
2 시점

무엇과 겹치나

3 계층

어느 계층의 지표가 비정상인가

  1. 네트워크: RTT·손실·재전송률, 인터페이스 오류·폐기
  2. 호스트: 코어별 CPU, CPU 스틸, softirq, NIC 폐기, 메모리 압박
  3. 게임 서버: 틱 시간, 소켓 수신 대기열(Recv-Q), 스레드별 CPU, GC 로그
  4. DB: 쿼리 지연, 잠금 대기, 복제 지연
  5. 클라이언트: 프레임 시간, 넷그래프, 크래시 보고

판정 신호표

확인할 것이렇게 보이면먼저 부를 곳
서버 소켓 수신 대기열(Recv-Q)서버 프로세스가 제때 못 읽어 쌓임게임개발팀서버 (틱 멈춤·GC·락)
연결별 재전송·RTT일부 연결만, 특정 ASN에 몰림인프라팀네트워크 외부통신사·유저 회선
한 호스트의 모든 연결인프라팀서버 장비·OS (NIC·커널)
패치 직후 서버 전체 재전송·대역폭 증가패킷 크기·빈도가 바뀜게임개발팀서버 인프라팀네트워크 (MTU·한도)
CPU 스틸·스로틀링·softirq·NIC 폐기증가인프라팀서버 장비·OS
한 스레드만 100%, 런큐 지연, GC 멈춤증가게임개발팀서버
DB 지연 증가, 쿼리 수는 그대로IOPS·잠금·다른 작업인프라팀DB 장비
DB 쿼리 수·모양이 패치 뒤 바뀜N+1, 새 쿼리게임개발팀서버
해외 지점의 합성 측정(RTT·손실)나쁨인프라팀네트워크 외부통신사
합성 측정은 정상인데 유저만 나쁨유저 환경 또는 클라이언트외부유저 환경 게임개발팀클라이언트
끊김 사유 분포하트비트 타임아웃↑ / RST↑ / 서버가 끊음↑NAT·경로 / 장비 / 서버
정확한 주기(정각, N분)예약 작업·백업·GC·이벤트그 일정을 만든 곳

그래프 모양으로 찾기

모니터링 그래프가 어떤 모양인지만 알아도 후보가 크게 줄어듭니다. 아래 13가지 모양마다 그 모양을 만드는 원인을 모았습니다. 원인 카드의 작은 그림도 같은 모양입니다. 실선은 주로 볼 지표, 점선은 함께 볼 지표(인원, 대기·오류 등), 옅은 점선은 평소 수준입니다.

가끔 무작위로 튐

간격 없이 불규칙하게 솟았다가 곧 돌아옵니다.

프레임 타임 스파이크, 과도한 외삽(데드 레커닝), 클라이언트 예측 불일치, 고정 타임스텝 따라잡기 폭주, 백그라운드 프로세스의 CPU 점유, 클라이언트 메모리 부족·스왑, NIC 절전·드라이버 문제, 와이파이 간섭·신호 약화, 5G↔LTE 잦은 전환 (5G 경계 지역), 회선 품질 불량, 링 버퍼 부족, 가상화 오버헤드·노이지 네이버, 커널 소켓 버퍼 부족, CPU 스틸 (가상 머신), 메모리 회수·컴팩션으로 인한 멈춤, 시스템 시계 점프 (NTP 스텝), 느린 클라이언트로 인한 블로킹 전송, 신뢰성 UDP 재전송 설정, RST 강제 종료로 마지막 데이터 유실, 게임 스레드의 동기 호출, 동기 로그 쓰기, 서버의 지연 로딩, DB 데드락, Redis 느린 명령, 로그·모니터링 과부하, 락스텝에서 가장 느린 플레이어 대기, 롤백 넷코드의 예측 실패, 타임스탬프 없는 도착 즉시 재생, 너무 엄격한 서버 검증, 명령 동기화의 경로 계산 불일치, 시야 등록 순서 꼬임, 기준 스냅샷 유실, 퇴장 알림 유실 (유령 개체), 개체 ID 재사용 혼동, 지연 급등으로 인한 불필요한 재전송

어느 순간부터 계단처럼 올라감

패치·설정 변경·경로 변경 같은 특정 시각을 기점으로 한 단계 올라가 그대로 머뭅니다.

해저 케이블·국제 회선 장애, BGP 경로 변경·수렴, DDoS 방어 경유·오탐, OS·커널·드라이버·펌웨어 업데이트 뒤 성능 변화, 패치로 트래픽 패턴이 바뀜, 인덱스 없는 쿼리, 실행 계획 변경으로 인한 쿼리 지연, 운영 중 스키마 변경(DDL) 잠금, 외부 서비스 의존, 경로 변경·ECMP 불량 경로

인원·부하를 따라 오름

동시 접속이나 한곳에 모인 인원이 늘면 그보다 가파르게 따라 오릅니다.

대규모 인원 렌더링 부하, 메인 스레드 패킷 처리 병목, 수신 버퍼 넘침, 같은 기기의 다른 앱이 대역폭 점유, 버퍼블로트 (공유기 대기열), 스위치 마이크로버스트, 스레드 과다와 컨텍스트 스위칭, 컨테이너 CPU 스로틀링 (CFS 쿼터), UDP 패킷의 IP 단편화, 블로킹 I/O 구조, 틱 예산 초과, 시야(AOI) 계산 폭증 (N²), 브로드캐스트 폭증, 단일 스레드 지역 과부하(핫스팟), 락 경합, 길찾기 폭주, 직렬화·압축 비용, 한 대상에 몰린 전투 (월드 보스), 할당 폭주, 핫 로우 잠금 경합, 복제 지연, 게이트웨이·프록시 경유, 존 이동 (서버 간 이관), 연결별 전송 예산·우선순위, 송신 버스트로 얕은 버퍼 넘침, 듀플렉스 불일치

한도에 닿아 평평해짐

처리량·연결 수가 어떤 값에 닿은 뒤 더 오르지 못하고 그때부터 대기·오류가 늘어납니다.

그래픽 메모리(VRAM) 부족, 공유기 성능 부족·과열, 통신사 속도 제한·트래픽 관리, DDoS로 인한 공유 회선 포화, 방화벽 세션 테이블 포화, 클라우드 NAT 게이트웨이 연결·포트 한도, 데이터센터 회선 포화, NIC 인터럽트 단일 코어 집중, 클라우드 PPS 한도 초과, NIC 대역폭 포화, 파일 디스크립터 한도, 서버 conntrack 테이블 포화, 서버 간 연결의 임시 포트 고갈, 메시지 큐 적체, 스레드 풀 고갈, GC 스래싱 (힙 여유 부족), 클라우드 디스크 버스트 크레딧 소진, IOPS 한도·대기열 포화, 커넥션 풀 고갈, 연쇄 장애, 로그인 대기열 상한·재접속 유예 부족, 메모리·VRAM 부족으로 스트리밍 실패, 폴리서의 초과분 폐기, 수신 서버 호스트의 패킷 폐기, 방화벽·연결 추적의 폐기, 중간 장비 처리 한도 초과 (방화벽·IPS·DDoS 방어)

처음부터 늘 높음

튀지 않고 계속 높은 값에 머뭅니다. 거리·경로·설계처럼 구조에서 오는 경우입니다.

보간 버퍼가 없거나 짧음, V-Sync와 렌더 대기열, 타이머 해상도, 디스플레이·입력 장치·프레임 생성 지연, 전파 지연 (물리적 거리), 우회 라우팅, 인터럽트 병합 과다, GRO/LRO 병합 대기 지연, 서버 전원 관리(C-state·주파수 조절)로 지연 튐, Nagle 알고리즘 + 지연 ACK, 캐시 미스, HDD 탐색 지연, 서버 응답 후에만 연출 (요청-응답 방식), 순차 왕복이 많은 프로토콜 (chatty), 스킬 선입력 없음, 클라이언트 권위, 이중 틱 대기, 낮은 스냅샷 전송률, 순서 뒤바뀜으로 인한 불필요한 빠른 재전송, RTO 설정이 환경과 맞지 않음, 중간 장비의 TCP 옵션 제거

일부만 높음

대부분은 정상이고 특정 유저·지역·통신사·기기만 따로 높습니다.

저장장치가 느려 에셋 스트리밍이 밀림, 클라이언트 크래시, 보안 프로그램의 패킷 검사, 오버레이 프로그램 간섭, RRC 상태 전환 지연 (모바일 무선 절전), 모바일 신호 약함·음영 지역, 공용 와이파이·회사망 제한, 위성 인터넷 (저궤도·정지궤도), ECMP 경로 하나의 불량, 국가·통신사 단위 UDP 제한·패킷 검사, DNS 장애·지연, VPN·게임 가속기 경유, 로드밸런서 쏠림·헬스체크 오판, 불량 케이블·포트 오류, MTU 불일치 (큰 패킷만 사라짐), 느린 클라이언트(slow consumer) 처리 정책, keepalive 기본값 2시간, 유휴 후 슬로 스타트, SO_REUSEPORT 분배 쏠림, NUMA 원격 메모리, 매크로·봇 과다, 매치메이킹·리전 배정 오류, 핑에 먹히는 짧은 판정 구간, 지연 보상 없는 판정, 지연 보상 과다, 호스트(방장) 구조, 선연출 뒤 서버 거절, 느린 사람이 남의 화면에서 몰아서 움직임, 도착 즉시 처리하는 서버의 몰아치기, 플레이어별 입력 버퍼 크기, 느린 파티원 한 명과 보스 기믹, 몬스터 제어 권한이 느린 클라이언트에 있음, 특정 캐릭터의 데이터가 비대함, 채널·인스턴스·페이즈 차이, 로딩 중 도착한 등장 알림 폐기, 고정 UDP 포트 충돌, IP·기기 기준 세션 구분 버그, 멀티 클라이언트 제한, 캐시·에셋 파일 동시 접근 충돌, 표시 옵션 차이, 클라이언트 버전·데이터 불일치, 시계 추정 오차로 개체 보류, 무선 구간 손실, 물리 오류 (불량 선·광모듈·커넥터), MTU 블랙홀 (큰 패킷만 반복 손실), ACK가 늦거나 사라짐 (업로드 포화)

연결이 한꺼번에 끊김

접속 수가 뚝 떨어지거나 끊김 수가 한순간 치솟습니다.

모바일 앱 백그라운드 전환, 와이파이 ↔ LTE·5G 전환, NAT 매핑 만료, 통신사 공유 IP (CGNAT), 로드밸런서 유휴 타임아웃, 클라우드 보안 그룹의 연결 추적 만료, 네트워크 장비 장애 전환(페일오버), OOM 킬러, 윈도우 UDP 소켓의 WSAECONNRESET 오류, 데드락, 서버 크래시, 무한 루프·로직 폭주, 코어 덤프 기록, DB 장애 전환, 긴 저장 주기로 인한 진행 유실, 부가 서버 장애, 배포·재시작, TLS 인증서 만료·설정 오류, 연결 도중 NAT·로드밸런서 매핑 만료

게임 코드 없이 얼마나 확인할 수 있나

원인마다 가장 쉬운 확인 수단을 셌습니다. 인프라 도구는 OS·네트워크·클라우드·DB 도구와 런타임 시작 옵션(GC 로그 등)으로 확인할 수 있어 게임 코드를 고치지 않아도 됩니다. 게임 로그·지표는 틱 시간, 끊김 사유처럼 게임이 남겨야 보이는 것입니다. 이 칸이 많은 층일수록 개발팀에 계측을 요청할 근거가 됩니다.

숫자 읽는 법

평균은 튐을 감춥니다. 초당 20틱 서버에서 틱의 1%만 느려도 5초에 한 번꼴로 모두가 멈칫하지만, 평균 틱 시간은 거의 변하지 않습니다. 그래서 백분위수를 함께 봅니다. p50(중앙값)은 절반이 이보다 빠른 값, p99는 100번 중 가장 느린 1번 근처의 값입니다. 유저가 “렉”으로 기억하는 것은 대개 p99 쪽입니다.

집계 간격도 튐을 감춥니다. 1분 평균 그래프에서는 1초짜리 멈춤이 1/60로 옅어집니다. 멈춤을 찾을 때는 같은 그래프의 최댓값이나 p99, 더 짧은 간격을 함께 봅니다.

지터는 패킷이 도착하는 간격이 얼마나 흔들리는지입니다. 평균 핑이 낮아도 지터가 크면 보간 버퍼가 비어 뚝뚝 끊김·순간이동이 생깁니다.

재는 방법무엇을 재나주의할 점
ping (ICMP)장비까지 왕복 시간라우터·서버가 ICMP 응답을 늦게 처리하거나 개수를 제한할 수 있어, 게임 패킷과 다르게 나올 수 있음. 막혀 있으면 아예 응답이 없음
mtr·traceroute구간별 지연·손실중간 장비 하나만 손실이 높고 그 뒤 구간이 정상이면, 그 장비가 ICMP 응답만 줄인 것일 가능성이 큼. 끝까지 이어지는 손실만 진짜 손실
TCP RTT (ss -ti의 rtt)커널이 연결마다 잰 왕복 시간실제 게임 연결의 값이라 가장 믿을 만함. 서버 쪽에서 유저별로 볼 수 있음
게임 안 핑게임이 자체 메시지로 잰 왕복 시간게임 루프 안에서 재면 프레임·틱 대기가 섞임. 회선이 멀쩡해도 서버·PC가 바쁘면 오름

바로 할 수 있는 것, 게임 코드에 더할 것

게임 코드 없이
  • 차원 붙이기: 접속·로드밸런서 로그의 클라이언트 IP에 국가·통신사(ASN)를 붙여 “해외만”, “특정 통신사만”이 보이게 합니다.
  • 연결 품질: 서버에서 ss -ti나 eBPF 도구로 연결별 RTT·재전송을 모아 ASN별로 봅니다.
  • 서버 밖에서 서버 속 보기: 소켓 대기열, 스레드별 CPU(pidstat -t), 런큐 지연, 시작 옵션만으로 켜는 GC 로그.
  • 경로 측정: 대상 국가·통신사 쪽에서 합성 측정(RIPE Atlas, 클라우드 리전의 측정용 서버)과 mtr.
  • 변경 기록: 배포·패치·설정·네트워크 작업을 모든 그래프에 세로선으로 표시합니다. “패치 이후”를 판정하는 출발점입니다.
게임 코드에 최소한으로
  • 클라이언트 요약 보고: 30~60초마다 RTT p50·p95, 지터, 손실, FPS, 프레임 스파이크 수, 빌드, 서버·채널.
  • 서버 틱 지표: 틱 시간 p50·p99, 틱 초과 수, 존별 인원, 연결별 송신 대기열.
  • 끊김 사유 코드: 하트비트 타임아웃·RST·서버가 끊음·인증 실패·점검을 양쪽에 같은 코드로.
  • 세션 ID와 시각: 모든 로그에 세션·캐릭터·서버 ID와 동기화된 UTC 시각.
  • 렉 신고 버튼: 최근 60초의 RTT·FPS·틱 공백을 세션 ID와 함께 올립니다.
T3도구

사례와 절차

자주 만나는 두 상황의 확인 순서와, 원개발사·운영사가 직접 공개한 실제 장애 사례를 모았습니다. 단계와 사례마다 관련 원인 카드로 이어집니다.

상황별 절차

패치 이후 렉

특정 패치·배포 뒤부터 렉 제보가 늘었을 때. “이번 업데이트부터 이상하다”는 제보가 모이거나, 그래프가 어느 시각부터 계단처럼 올라가 그대로 머무는 경우에 쓴다.

  1. 시작 시각을 확정하고 그 앞뒤의 변경을 모두 모은다: 제보가 처음 몰린 시각과 그래프가 계단처럼 오른 시각을 찾고 그 앞뒤로 나간 변경을 빠짐없이 적는다. 클라이언트 패치, 서버 배포, 설정 변경, DB 스키마 변경(DDL)과 재시작, 네트워크·방화벽 작업, 인프라 교체(인스턴스 종류·커널·드라이버)를 함께 본다. 배포 때마다 모니터링 도구의 주석(annotation) 기능으로 모든 그래프에 세로선을 남겨 두면 이 단계가 금방 끝난다. 게임 패치와 인프라 작업이 같은 점검 시간에 나갔으면 둘 다 후보로 남긴다. 먼저 부를 곳: 변경을 낸 게임개발팀과 인프라팀 양쪽.
  2. 범위를 나눈다: 빌드·기기·서버·지역: 이상이 어느 차원에 몰렸는지 본다. 새 빌드 사용자만 나쁘면 클라이언트, 특정 OS·그래픽카드·기기만 나쁘면 클라이언트 성능이나 드라이버, 특정 서버·채널·존만 나쁘면 서버, 특정 국가·통신사만 나쁘면 네트워크 경로, 모두가 동시에 나쁘면 공용 자원(DB·로드밸런서·게이트웨이)이나 방금 나간 서버 배포를 먼저 의심한다. 클라이언트 텔레메트리에 빌드 번호가 있으면 옛 빌드와 새 빌드의 핑·FPS·프레임 스파이크·접속 끊김 횟수를 나란히 놓는다. 핑은 그대로인데 FPS만 나빠졌으면 네트워크보다 클라이언트 성능 쪽이다. 먼저 부를 곳: 빌드·기기에 몰리면 게임개발팀(클라이언트), 서버·채널에 몰리면 호스트 지표가 정상일 때 게임개발팀(서버)·비정상일 때 인프라팀(서버 장비·OS), 국가·통신사에 몰리면 인프라팀(네트워크).
  3. 새 버전과 옛 버전을 같은 시간대에 비교한다: 배포 전후만 비교하면 요일·시간대·이벤트에 따른 변화가 섞여 판단이 흐려진다. 가능하면 새 버전을 일부 서버(카나리)에 먼저 올리고 같은 시간대의 옛 버전 서버(대조군)와 틱 시간 p50·p99, 틱 초과 수, CPU, 메모리, 오류율을 나란히 비교한다. 이미 전체에 배포했으면 지난주 같은 요일·같은 시간대와 비교한다. 서버 전체 평균만 보면 일부 서버·존의 문제가 묻히므로 서버·존별로 나눠 본다. 먼저 부를 곳: 게임개발팀(서버).
  4. 트래픽 지문을 전후로 비교한다: 서버 코드를 몰라도 네트워크 쪽에서 보이는 값으로 패치가 트래픽 모양을 바꿨는지 확인한다. 유저당 초당 패킷 수(pps)와 바이트, 평균·최대 패킷 크기, 연결 수, 틱마다 한꺼번에 나가는 송신 버스트 크기를 전후로 비교한다. UDP 패킷이 경로 MTU(보통 1,500바이트)를 넘기 시작했으면 IP 단편화가 일어난다. 프래그먼트 하나만 잃어도 패킷 전체를 잃고 프래그먼트를 아예 버리는 NAT·방화벽도 있다. 중간에 MTU가 작은 구간(터널·VPN)을 지나는 유저는 큰 패킷만 사라진다. pps가 늘었으면 클라우드 인스턴스의 PPS 한도나 방화벽·DDoS 방어 장비의 처리 한도에 닿지 않았는지 본다. 먼저 부를 곳: 지문이 바뀌었으면 증거를 붙여 게임개발팀(서버), 지문은 그대로인데 손실·재전송만 늘었으면 인프라팀(네트워크).
  5. DB 쿼리의 종류와 횟수를 전후로 비교한다: DB 지연이 올랐으면 쿼리 수(QPS)도 함께 올랐는지부터 본다. PostgreSQL의 pg_stat_statements나 MySQL Performance Schema의 digest 요약은 값만 다른 쿼리를 한 종류로 묶어 실행 횟수와 총 시간을 모아 준다. 패치 전후의 상위 쿼리 목록을 비교하면 새로 생긴 쿼리, 횟수가 몇 배로 는 쿼리(N+1), 인덱스 없이 테이블 전체를 읽는 쿼리(MySQL은 SUM_NO_INDEX_USED 열)가 드러난다. 먼저 부를 곳: QPS나 쿼리 모양이 바뀌었으면 게임개발팀(서버), 쿼리는 같은데 지연만 늘었으면 인프라팀(DB: 실행 계획·IOPS·잠금).
  6. 호스트와 서버 프로세스 지표로 계층을 가른다: 코드 없이 OS에서 보이는 값으로 서버 안쪽과 호스트를 가른다. 서버 소켓의 수신 대기열(Recv-Q)이 쌓이면 서버 프로세스가 제때 읽지 못한다는 신호다(틱 멈춤·GC·락). 스레드 하나만 100%면 단일 스레드 병목이고 GC 로그의 멈춤 시간이 늘었으면 메모리 사용 패턴이 바뀐 것이다. 로그 레벨을 올린 채 배포해 로그 쓰기가 늘지 않았는지도 본다. 반대로 CPU 스틸·스로틀링·NIC 드롭이 늘었으면 같은 시각에 바뀐 인프라(인스턴스 종류·커널·컨테이너 한도)를 본다. 먼저 부를 곳: 프로세스 안쪽 신호면 게임개발팀(서버), 호스트 신호면 인프라팀(서버 장비·OS).
  7. 되돌려서 확정하고 기록을 남긴다: 가장 유력한 변경을 일부 서버나 일부 유저에게서만 되돌리거나(롤백, 기능 플래그 끄기) 설정을 이전 값으로 돌려, 증상이 함께 사라지는지 본다. 되돌린 쪽만 나아지면 원인이 확정된다. 되돌리는 작업도 재시작과 콜드 캐시로 잠깐 느려질 수 있으니, 급하지 않으면 한가한 시간대에 한다. 결과는 원인 ID와 함께 장애 기록에 남기고 패킷 크기·쿼리 수·틱 시간 한도를 다음 패치의 배포 전 점검 항목으로 옮긴다. 먼저 부를 곳: 변경을 낸 팀.

해외 국가·지역 추가

서비스 국가를 새로 열거나 새 리전·데이터센터를 추가할 때. 오픈 전 점검과, “국내는 괜찮은데 새 국가 유저만 렉”이라는 제보를 가를 때 함께 쓴다.

  1. 현지 통신사별 경로 품질을 오픈 전에 잰다: 대상 국가의 주요 통신사(ASN)마다 게임 서버 후보 위치까지 왕복 시간(RTT) 분포, 지터, 손실을 잰다. 평균 하나에는 통신사별 차이가 묻히므로, 통신사별 중앙값과 95퍼센타일을 저녁 피크와 새벽으로 나눠 본다. 공개 측정망 RIPE Atlas에서는 국가·ASN을 골라 전 세계 프로브에서 ping·traceroute를 보낼 수 있다. 후보 리전에 임시 VM을 띄워 재도 된다. 중간 장비가 ICMP 응답을 제한하기도 하므로 가능하면 게임과 같은 프로토콜·포트로도 잰다. 특정 통신사만 유독 먼 도시를 거쳐 가면 피어링·경로 문제다. 통신사는 지연보다 비용이 낮은 경로를 고르기 때문에 가까운 곳도 멀리 돌아가는 일이 생긴다. 먼저 부를 곳: 인프라팀(네트워크), 경로가 통신사 쪽이면 외부(통신사·IX).
  2. 측정값을 게임 설계가 버티는 한도와 비교한다: 잰 RTT·지터를 게임의 판정 구간(회피·패링 같은 반응 시간), 지연 보상 한도, 보간 버퍼 길이, 입력 버퍼 크기와 비교한다. 예를 들어 패링 판정이 0.2초면, 왕복 지연과 보간 버퍼를 더한 값이 그보다 긴 통신사 사용자는 제때 반응해도 늦는다. 지연 보상을 넓혀 맞추면 이번에는 맞는 쪽에서 “벽 뒤에서 맞았다”는 제보가 는다. 한도를 넘는 통신사가 많으면 인프라팀은 리전·엣지 PoP를 더 가깝게 두는 방안을, 게임개발팀은 판정·보간·지연 보상 값을 검토한다. 기준표는 백서의 “동기화 방식” 장에 있다. 먼저 부를 곳: 게임개발팀(서버·클라이언트: 설계 한도), 인프라팀(네트워크: 리전·PoP 위치).
  3. MTU와 UDP 통과 여부를 확인한다: 현지 망에서 게임의 가장 큰 패킷이 온전히 지나가는지 확인한다. 단편화 금지(DF) 표시를 한 핑을 크기별로 보내 경로 MTU를 재고 PPPoE·터널·모바일망처럼 1,500바이트보다 작은 구간이 있는지 본다. UDP 같은 데이터그램 전송의 표준(RFC 8899)은 IPv4에서 대부분의 경로를 지날 수 있는 기본 크기로 1,200바이트를 권한다. 게임의 최대 패킷이 이보다 크면 줄이거나 나눠 보내는 방안을 게임개발팀과 정한다. 공용 와이파이·회사망·일부 통신사에서 UDP나 게임 포트가 막히거나 속도가 제한되는지도 확인하고, 막힐 때 쓸 대체 경로(TCP·443 포트)가 있는지 본다. 먼저 부를 곳: 인프라팀(네트워크)과 게임개발팀(서버: 패킷 크기).
  4. NAT·CGNAT의 유휴 타임아웃을 재고 하트비트 간격을 맞춘다: 현지 가정용 공유기와 모바일망(CGNAT)이 유휴 UDP 연결의 매핑을 얼마 만에 지우는지 잰다. 시험마다 테스트 기기에서 서버로 패킷을 하나 보내 매핑을 만든 뒤 기기는 아무것도 보내지 않고, 서버가 정해 둔 시간(30초, 60초, 120초 …)이 지난 뒤 기기로 패킷을 보내게 한다. 기기가 그 패킷을 받지 못하기 시작하는 시간이 그 망의 유휴 타임아웃이다. 표준(RFC 4787)은 UDP 매핑이 2분 전에 만료되면 안 되고 기본 5분 이상을 권하지만, 장비마다 값이 크게 달라 더 짧게 지우는 장비도 있다. 매핑은 기기에서 나가는 패킷으로만 확실히 갱신되므로 하트비트는 클라이언트가 보낸다. 그 간격이 잰 값과 로드밸런서·클라우드 보안 그룹의 유휴 타임아웃 가운데 가장 짧은 값의 절반 이하인지 본다. 먼저 부를 곳: 게임개발팀(클라이언트: 하트비트 간격, 서버: 타임아웃 값), 인프라팀(로드밸런서·보안 그룹 설정).
  5. 현지에서 거치는 외부 서비스와 보안 장비를 확인한다: 현지 플랫폼 로그인·결제·본인 인증이 제 속도로 응답하는지, 현지 DNS에서 로그인·패치 서버 주소가 제대로 풀리는지, CDN이 그 나라에 가까운 거점에서 패치를 내려 주는지 확인한다. DDoS 방어·방화벽의 국가 차단 규칙과 속도 제한에 새 국가의 IP 대역이 걸리지 않는지 보고, 특히 여러 가입자가 IP 하나를 나눠 쓰는 CGNAT 대역이 한꺼번에 차단되지 않는지 본다. 먼저 부를 곳: 인프라팀(보안 장비·DNS·CDN), 외부(플랫폼·결제사·통신사).
  6. 오픈 뒤에는 국가·ASN별로 나눠 본다: 접속 로그·로드밸런서 로그의 클라이언트 IP에 국가와 ASN을 붙여 국가·통신사별로 RTT, 재전송, 접속 끊김 횟수와 사유(하트비트 타임아웃·RST·서버 킥)를 본다. MaxMind GeoLite ASN 같은 무료 데이터베이스로 IP를 ASN과 조직 이름으로 바꿀 수 있다. 현지 개인정보 규정에 맞춰 IP는 /24나 ASN 단위로 줄여 보관한다. 한 ASN에만 몰리면 그 통신사 경로(인프라팀·외부), 새 국가 전체가 나쁘면 거리와 설계 한도(인프라팀·게임개발팀), 저녁에만 나빠지면 피어링 혼잡을 먼저 본다. 일부 유저만 늘 핑이 높으면 GeoIP 오류·VPN·파티장 기준 배정으로 먼 리전에 배정되지 않았는지 게임개발팀(서버)과 함께 본다. 합성 측정은 정상인데 유저만 나쁘면 유저 환경이나 클라이언트 쪽이다.
  7. 먼 지역 유저가 다른 유저에게 주는 영향을 확인한다: 멀리서 접속한 유저가 늘면 그 사람 화면만 나빠지는 데서 끝나지 않는다. 느린 사람의 입력이 몰려 도착해 다른 사람 화면에서 그 캐릭터만 몰아치기로 움직이고, 서버의 속도·쿨타임 검사에 걸려 고무줄이나 스킬 거절이 생긴다. 파티 기믹에서는 느린 한 사람의 늦은 반응이 파티 전체의 실패가 되고 락스텝 방식에서는 가장 느린 사람을 모두가 기다린다. 새 국가 오픈 뒤 기존 유저의 “특정 캐릭터만 이상해 보임” 제보가 늘었는지 보고 입력 버퍼·검증 허용치·매칭 지역 분리를 게임개발팀과 정한다. 먼저 부를 곳: 게임개발팀(서버).

실제 장애 사례

게임사와 인프라 회사가 스스로 공개한 사후 분석(포스트모템)만 골랐습니다. 요약은 원문이 밝힌 내용 안에서 썼고 자세한 경위는 원문을 보세요.

CCP Games 2014: EVE Online HED-GP 대규모 함대전의 서버 과부하

2014년 1월 회고가 다룬 HED-GP 성계의 대규모 함대전에서 서버가 크게 과부하됐다. Time Dilation(과부하 때 게임 시간을 늦추는 기능)이 하한인 10%에 닿아 전장 전체가 슬로우모션이 된 뒤에도 부하가 계속 쌓였고, 모듈의 정지·반복 작동을 처리하는 작업이 밀린 정도(Dogma Lateness)가 최대 게임 시간 193초, 실제 시간으로 약 32분에 이르렀다. 규모가 거의 같았던 2013년 7월 6VDT 전투는 최대 42초(실제 약 7분)였다. CCP는 성능 분석 도구가 그 자체로 부하를 더해 이런 상황에서는 돌리지 않으므로 확실하지 않다고 전제하고, 두 가지를 유력한 원인으로 꼽았다. 하나는 전투가 길어지며 처리하지 못하고 계속 쌓인 부하다. 다른 하나는 드론 사용 증가로, 전투 동안 배치된 드론 수(중복 제외)는 6VDT 21,123개, HED-GP 38,852개로 84% 많았다. 한 명의 행동을 보는 모두에게 알려야 하는 전송은 인원의 제곱(O(n²))으로 늘어나는데, 드론은 공격 한 번에 메시지가 더 많다. 드론이 공격 대상을 고르는 코드도 같은 전장의 공격 가능한 대상을 자주 전부 살펴서, 비용이 n²에 가깝게 늘어난다.

인원이 몰린 한 지역의 처리량이 한계를 넘으면 그 지역 전체가 슬로우모션이 되고, 전투가 길수록 밀린 처리가 쌓여 입력 지연이 커진다. 확인 신호는 그 지역을 맡은 서버(노드)의 틱 시간·밀린 작업량과 인원·개체 수이고, 다른 지역은 멀쩡한 것이 특징이다. 주 담당은 게임개발팀(서버)이며 한 행동을 알릴 대상의 범위와 AI의 대상 탐색 비용이 고칠 곳이다. 게임 시간을 늦추는 설계는 과부하를 없애지는 못하지만 모두가 같은 속도로 느려지게 해서 일부 행동만 한없이 밀리는 일을 막는다. 원문

Riot Games 2015: 멀리 돌아가던 League of Legends 트래픽과 Riot Direct

Riot Games가 인터넷이 실시간 게임에 맞지 않는 이유를 설명한 기술 글이다. League of Legends 유저가 제보한 실제 트래픽은 샌프란시스코에서 포틀랜드로 가면서 로스앤젤레스, 덴버, 시애틀을 거쳐 갔다. 곧장 가면 14ms면 될 것이 70ms 걸렸다. Riot은 라우터가 넘쳐 패킷이 버려지면 다른 챔피언이 화면에서 튀어 다니고 투사체가 순간이동하는 것처럼 보인다고 설명했다. Riot은 경로와 라우터를 원인으로 들었다. 백본 사업자와 통신사는 지연이 가장 짧은 경로보다 비용이 가장 싼 경로로 트래픽을 보내고, BGP로 정해진 경로가 멀리 돌아가면 거치는 라우터 수도 늘어난다. 라우터는 패킷 크기와 상관없이 개수만큼 처리 부담을 진다. 게임 패킷은 55바이트 안팎이라 같은 데이터양이면 1,500바이트 패킷보다 개수가 27배이고, 그만큼 라우터 입력 버퍼를 빨리 채운다. Riot의 설명으로는 과부하가 걸리면 UDP 패킷부터 버리는 라우터도 많다. 해결책으로 Riot은 미국의 큰 인터넷 거점 10곳에 라우터를 두고 가능한 한 많은 통신사와 직접 연결(피어링)하는 자체 망 Riot Direct를 만들었다. 2부에 따르면 핑 80ms 미만으로 플레이하는 유저 비율이 9개월 남짓 동안 31%에서 50%로 올랐고, 게임 서버를 시카고로 옮긴 뒤 하룻밤 사이 80%가 됐다.

같은 나라 안에서도 특정 통신사 사용자만 핑이 유독 높으면 경로를 의심한다. 확인 신호는 통신사(ASN)별 RTT 분포와 traceroute에 찍히는 경유 도시다. 주 담당은 인프라팀(네트워크)이고 통신사와의 직접 피어링, IX 연결, 서버 위치 선택으로 고친다. 통신사 쪽 경로 정책은 외부(통신사)와 협의할 일이다. 이 사례처럼 서버를 사용자 분포의 중심 가까이 옮기기만 해도 효과가 크다. 원문

Riot Games 2020: League of Legends 유럽·브라질 서버의 엣지 호스트 과부하

2020년 2월 말 League of Legends의 EUW·EUNE·BR 서버에서 여러 차례 장애가 나 새로 시작되는 게임 수가 크게 줄었다. 매칭·게임 서버 같은 백엔드 서비스는 모두 상태가 정상이었지만 들어오는 트래픽이 거의 없었다. Riot은 불안정할 수 있는 클러스터에서 토너먼트 모드(Clash)를 열지 않으려고 일정을 한 주 미뤘다. 회고에 장애마다 이어진 시간은 적혀 있지 않다. 세 가지가 겹쳤다. 한 서비스로 가는 요청이 잘못 만들어져 특정 경우에 계속 실패하고 재시도되면서 요청이 폭증했다. 컨테이너 시스템과 OS 버전의 알려진 궁합 문제로 OS 내부 메모리가 새고 있었는데, 업그레이드는 Riot 전체 컨테이너 환경의 약 60%에서만 끝났고 유럽·라틴아메리카 클러스터는 진행 중이었다. 인터넷 트래픽을 받아 걸러 백엔드로 보내는 엣지 컨테이너는 같은 샤드(서버군) 안에서는 떨어지게 배치됐지만 다른 샤드끼리 몰리는 것은 막지 못해, 장애 때마다 적어도 세 샤드의 엣지 컨테이너가 호스트 한 대에 몰려 있었다. 그 호스트에 재시도 폭증이 겹쳤고 메모리 누수로 호스트가 멈췄다.

뒷단 서비스가 모두 “정상이지만 트래픽이 안 들어온다”고 답하면 그 앞단(엣지·게이트웨이·로드밸런서)을 본다. 확인 신호는 호스트별 인바운드 연결 수의 쏠림과 특정 요청의 실패·재시도 비율이다. 주 담당은 게임개발팀(서버: 잘못된 요청과 재시도 방식)이고 컨테이너 배치 규칙·OS 업그레이드·쏠림 경보는 인프라팀(서버 장비·OS)이 맡는다. Riot은 요청 코드를 고치고 재시도가 급증하지 않게 바꿨으며 샤드 사이 분산을 구현하기 전까지 쏠림 경보를 두었다. 원문

Riot Games 2021: League of Legends EUW 5시간 장애: 부가 DB 하나가 서버 전체를 멈춤

2021년 1월 22일 League of Legends EUW 서버가 5시간 조금 넘게 제대로 동작하지 않았다. 로그인한 유저 수와 게임 중인 유저 수 지표가 한꺼번에 끊겼고 두 차례 재시작 사이에는 로그인은 늘어도 게임은 거의 시작되지 않았다. 중요하지 않은 기능을 맡던 DB의 주 서버에 하드웨어 고장이 났고 그 DB는 예비 서버로 자동 전환하도록 설정되어 있지 않았다. DB마다 커넥션 풀은 나뉘어 있었지만 모든 풀이 같은 스레드 풀을 썼다. 고장 난 DB에 보낸 작업이 끝나지 않은 채 스레드를 점유해 시스템 전체가 쓸 스레드가 바닥났다. 경보가 쏟아지는 가운데 최근 겪은 악의적인 네트워크 공격과 다른 지역의 하드웨어 작업을 먼저 의심하느라, 고장 난 DB의 경보는 약 1시간 뒤에야 눈에 띄었다. 모든 시스템이 한 JVM에서 도는 구조라, 재시작 뒤 재접속 부하 속에서 GC가 몇 초씩 프로세스를 멈추자 지표 수집에도 큰 공백이 생겼다. 로그인 대기열도 설정한 한도를 지키지 않아 유입이 들쭉날쭉했다.

중요하지 않다고 여긴 부가 DB 하나도 스레드 풀 같은 공유 자원을 통해 전체를 멈출 수 있다. 확인 신호는 DB별 대기 중인 요청 수와 스레드 풀 사용률, 그리고 로그인 수에 비해 게임 시작 수가 너무 적은 비율이다. 담당은 게임개발팀(서버: 스레드 풀 격리·타임아웃)과 인프라팀(DB: 자동 전환)이다. 경보가 쏟아질 때는 최근에 겪은 문제(공격 등)부터 의심하기 쉬우니, 판정 순서(범위 → 시점 → 계층)대로 하나씩 배제한다. 재시작 뒤에는 로그인 대기열이 설정대로 유입을 제한하는지도 함께 본다. 원문

Roblox 2021: Roblox 73시간 장애: 서비스 디스커버리(Consul) 클러스터의 경합

장애는 2021년 10월 28일 오후(태평양 시간) Consul 서버 한 대의 높은 CPU 부하로 시작됐다. 16시 35분 접속 중인 유저 수가 평소의 절반으로 떨어진 뒤 서비스 전체가 멈췄다. 10월 31일 16시 45분에야 모든 유저가 다시 들어올 수 있었고 장애 시작부터 73시간이 걸렸다. Roblox는 매일 5천만 명이 이용한다고 밝혔다. Roblox는 서비스 디스커버리(서비스끼리 서로의 주소를 찾는 기능), 헬스체크, KV 저장소에 HashiCorp Consul을 쓰는데 Consul 클러스터 하나가 여러 워크로드를 함께 맡고 있었다. 근본 원인은 두 가지였다. 첫째, 몇 달에 걸쳐 넓혀 온 Consul의 새 streaming 기능을 장애 전날 트래픽 라우팅 서비스에도 켜고 그 서비스의 노드 수를 50% 늘렸다. 이 기능은 읽기와 쓰기가 모두 매우 많은 부하에서 공유 자원(Go 채널) 하나에 경합을 일으켰다. 장애 중 바꿔 넣은 코어 수가 더 많은 듀얼 소켓(NUMA) 서버에서는 경합이 더 심했다. 둘째, Consul이 Raft 로그 저장에 쓰는 BoltDB의 빈 페이지 목록(freelist) 관리가 병적으로 느려져, 16kB 이하를 추가할 때마다 7.8MB를 디스크에 썼다. 평소 300ms 미만이던 KV 쓰기 지연 중앙값이 2초가 됐고 느린 리더 서버에서는 TCP 버퍼가 가득 차는 제로 윈도우도 관찰됐다. 텔레메트리가 Consul에 기대고 있어 원인을 찾는 데 필요한 지표도 함께 사라졌다.

여러 서비스가 함께 기대는 기반 시스템(서비스 디스커버리·설정 저장소·인증)이 느려지면 모든 기능이 한꺼번에 멈춘다. 확인 신호는 그 시스템의 쓰기 지연·리더 교체·CPU와, 장애 직전의 설정 변경이다. 담당은 게임개발팀(서버)과 인프라팀(서버 장비·OS) 양쪽이다. 모니터링은 감시 대상 시스템에 기대지 않게 분리해야 장애 때도 지표를 볼 수 있다. 복구할 때는 캐시가 비어 있어 한꺼번에 받으면 다시 무너질 수 있으므로, Roblox는 DNS로 입장할 유저 비율을 조절하며 약 10%씩 늘렸다. 원문

Square Enix 2021: FINAL FANTASY XIV 확장팩 출시 혼잡과 로그인 대기열 오류

2021년 12월 확장팩 Endwalker의 얼리 액세스부터 각 월드가 극심하게 붐볐다. 로그인 대기열이 길어졌고 캐릭터 선택 화면에서 로그인할 때나 대기열에서 기다리는 중에 Error 2002가 자주 났다. 일부 월드·존의 다운(Error 3001)과 대기열 타임아웃(Error 4004)도 있었다. 12월 11일 공지 시점에도 얼리 액세스 8일째 혼잡이 이어지고 있었다. Error 2002는 두 경우에 난다. 하나는 논리 데이터센터마다 대기 인원이 17,000명을 넘을 때다. 대기열이 너무 길어져 로그인 서버가 다운되는 것을 막으려는 상한이고 이때는 클라이언트가 완전히 종료된다. 12월 7일 개발용 예비 장비를 로비 서버에 투입해 상한을 올리자 이 오류는 줄었지만 대기열은 오히려 길어졌다. 다른 하나는 대기 중 유저의 회선이 불안정할 때다. 대기 시간이 길어지면서 인터넷 경로의 패킷 손실이나 와이파이 불안정으로 연결이 잠깐 끊기는 일이 늘었다. 로비 서버는 수십 초에서 1분 정도 재연결을 기다려 주고 그 안에 다시 붙으면 대기열 중간부터 이어 가지만 넘기면 맨 뒤로 가야 한다. Square Enix는 제보 대부분이 이 경우라고 밝혔다. 반도체 부족으로 월드를 바로 늘릴 수도 없었다.

대기열이 길어질수록 대기 중인 유저의 짧은 회선 끊김이 접속 오류로 바뀐다. 같은 혼잡에서도 오류가 와이파이나 불안정한 회선을 쓰는 사람에게 몰려 “일부에게만” 생기는 문제가 된다. 확인 신호는 대기열 길이·대기 시간과, 끊김 사유 가운데 대기 중 연결 끊김의 비율이다. 주 담당은 게임개발팀(서버: 대기열 상한과 재연결 유예 시간)이고 로비·월드 서버 증설은 인프라팀이 함께 한다. 재연결 유예 시간을 넉넉히 두면 유저 회선의 짧은 끊김이 대기 순번을 잃는 일로 번지는 것을 줄일 수 있다. 원문

Cloudflare 2020: Cloudflare 백본 설정 오류로 일부 도시의 트래픽 손실

많은 게임이 웹·API·DDoS 방어를 CDN 사업자에 맡기므로, 게임도 함께 영향을 받는 유형의 인프라 장애다. 2020년 7월 17일 21:12부터 21:39(UTC)까지 27분 동안 Cloudflare 네트워크 전체 트래픽이 약 50% 줄었다. 영향은 백본에 연결된 미국·유럽·러시아·브라질의 일부 도시 거점에 한정됐고, 다른 거점은 정상이었다. 뉴어크–시카고 백본 구간 장애로 애틀랜타–워싱턴 구간이 혼잡해지자, 엔지니어가 애틀랜타의 백본 트래픽을 덜어 내려고 라우터 설정을 바꿨다. 정책 항목(term) 전체를 꺼야 했는데 그 안의 조건(prefix-list)만 끄는 바람에, 애틀랜타 라우터가 모든 BGP 경로를 더 높은 우선순위(local-preference 200)로 백본 전체에 퍼뜨렸다. 각 거점이 자기 서버로 가는 경로에 준 우선순위는 100이어서 백본에 연결된 거점의 트래픽이 모두 애틀랜타로 몰렸다. 애틀랜타는 과부하되고 영향받은 거점은 처리할 트래픽이 거의 없어졌다. 애틀랜타 라우터를 백본에서 빼자 복구됐다. Cloudflare는 공격이나 침해와 관계가 없다고 밝혔다.

특정 도시·지역 유저만 한꺼번에 접속 끊김이나 접속 불가·무한 로딩을 겪고 나머지는 멀쩡하면, 직전의 경로 설정 변경을 먼저 의심한다. 그래프에서는 한 거점만 CPU·트래픽이 치솟고 영향받은 거점은 오히려 0 가까이 떨어진다. 주 담당은 인프라팀(네트워크)이고 사업자 쪽 장애라면 외부다. Cloudflare는 백본 BGP 세션에 받을 수 있는 경로 수 상한(maximum-prefix)을 두기로 했고, 한 거점이 다른 거점의 트래픽을 끌어가지 못하게 우선순위를 조정했다. 원문

Fastly 2021: Fastly CDN 전 세계 오류

많은 게임이 패치 파일·런처·웹 페이지를 CDN으로 내려보내므로, 게임도 함께 영향을 받는 유형의 인프라 장애다. 2021년 6월 8일 09:47(UTC)부터 Fastly 네트워크의 85%가 오류를 돌려주었다. 49분 안에 네트워크의 95%가 정상으로 돌아왔고 12:35에 장애가 수습됐다. 5월 12일 시작한 소프트웨어 배포에, 특정 고객 설정이 특정 조건을 만날 때 발동하는 버그가 들어 있었다. 6월 8일 한 고객이 정상적인 설정 변경을 올리면서 그 조건이 맞아떨어졌다. Fastly는 1분 만에 이상을 감지했고 원인이 된 고객 설정을 찾아 끄자 복구가 시작됐다. 버그 수정 배포는 같은 날 17:25에 시작됐다.

배포한 지 몇 주 지난 코드도 드문 조건을 만나면 한순간에 전 세계 장애가 된다. 게임 쪽 확인 신호는 패치·런처·웹 요청의 HTTP 오류율이 모든 지역에서 동시에 오르는 것과 CDN 사업자의 상태 페이지다. 이미 접속한 게임 연결은 CDN을 거치지 않으면 멀쩡하고 새 접속·패치 다운로드·웹 로그인만 막히는 것이 특징이다. 주 담당은 외부(CDN 사업자)이고 게임개발팀·인프라팀은 CDN을 둘 이상 쓰거나 원본 서버로 바로 받는 우회 경로를 준비해 둔다. 원문

Meta 2021: Facebook 백본 명령 하나로 DNS까지 사라진 장애

게임사의 자체 네트워크와 DNS에서도 똑같이 생길 수 있는 유형의 인프라 장애다. 2021년 10월 4일 Facebook(현 Meta)의 서비스가 전 세계에서 접속되지 않았다. 데이터센터를 잇는 백본이 모두 끊기고 인터넷 쪽에서 Facebook의 DNS 서버를 찾을 수 없게 됐다. 회고에 장애가 이어진 시간은 적혀 있지 않다. 정기 유지보수 작업 중 전 세계 백본 용량을 확인하려고 내린 명령이 의도와 달리 백본의 모든 연결을 끊었고, 이런 명령을 막아야 할 감사 도구는 버그 때문에 막지 못했다. 소규모 거점의 DNS 서버는 데이터센터와 통신할 수 없으면 스스로 비정상으로 판단해 BGP 광고를 거두도록 되어 있어서, DNS 서버가 살아 있는데도 인터넷에서 닿을 수 없게 됐다. 평소의 접속 경로와 대역 외(out-of-band) 접속이 모두 끊기고 내부 도구도 DNS를 잃어, 엔지니어를 데이터센터로 직접 보내야 했고 보안 절차 때문에 시간이 더 걸렸다. 복구 때는 데이터센터마다 전력 사용이 수십 MW씩 줄어 있어 한꺼번에 되돌리면 전력 설비부터 캐시까지 위험할 수 있다고 보고, 부하를 단계적으로 올렸다.

모든 지역·모든 통신사에서 동시에 접속 불가·무한 로딩이 생기면 게임 서버보다 DNS와 BGP 경로를 먼저 본다. 외부 DNS 조회와 공개된 BGP 경로 정보로 회사 밖에서도 확인할 수 있다. 주 담당은 인프라팀(네트워크)이다. 장애 때 쓸 대역 외 접속 경로와 내부 도구가 같은 DNS·네트워크에 기대지 않는지 미리 점검하고, 복구할 때는 재접속이 한꺼번에 몰리지 않게 부하를 단계적으로 올린다. 원문

AWS 2021: AWS us-east-1 내부 네트워크 혼잡

많은 게임이 서버·로그인·데이터를 퍼블릭 클라우드에 두므로, 게임도 함께 영향을 받는 유형의 인프라 장애다. 2021년 12월 7일 오전 7시 30분(태평양 표준시) 북버지니아 리전(us-east-1)의 내부 네트워크가 혼잡해졌다. 7시 33분부터 EC2 API 오류와 지연이 늘어 새 인스턴스를 띄우기 어려웠다(인스턴스 시작은 오후 2시 40분 회복). 콘솔 로그인 실패, Route 53 설정 변경 불가, CloudWatch 지표 지연과 일부 유실도 이어졌다. 네트워크 장비는 오후 2시 22분에 완전히 회복됐다. 이미 돌던 EC2 인스턴스와 기존 DNS 응답은 영향을 받지 않았다. 메인 네트워크에 있는 한 서비스의 용량을 늘리는 자동 작업이 내부 네트워크의 수많은 클라이언트에서 예상하지 못한 동작을 일으켜 연결 시도가 폭증했다. 내부 네트워크와 메인 네트워크를 잇는 장비가 넘쳐 통신이 지연됐고 지연이 다시 연결 시도와 재시도를 늘려 혼잡이 이어졌다. 클라이언트에는 이런 혼잡 때 요청 간격을 늘리는 백오프 동작이 있었지만 잠재된 결함 때문에 제대로 작동하지 않았다. 내부 모니터링도 같은 네트워크에 기대고 있어, 운영팀은 실시간 지표 없이 로그를 보며 대응했다.

재시도가 간격을 늘리지 못하면 짧은 혼잡이 몇 시간짜리 장애가 된다. 게임 쪽에서 보면 이미 돌던 게임 서버는 멀쩡해도, 새 서버 증설(오토스케일링), 클라우드 API를 쓰는 로그인·매칭·결제, 모니터링이 함께 막힐 수 있다. 확인 신호는 클라우드 사업자의 상태 페이지와 클라우드 API 오류율, 인스턴스 시작 실패다. 주 담당은 외부(클라우드 사업자)다. 게임개발팀은 모든 재시도에 무작위 간격의 지수 백오프와 횟수 제한을 두고 인프라팀은 증설이 막혀도 버틸 여유 용량과 다른 리전 대안을 준비한다. 원문

Cloudflare 2025: Cloudflare 공용 DNS 1.1.1.1 장애

유저가 기기나 공유기에 직접 설정해 쓰는 공용 DNS 리졸버의 장애로, 그 설정을 쓰는 유저에게만 모든 게임과 서비스가 함께 막히는 유형이다. 2025년 7월 14일 21:52부터 22:54(UTC)까지 62분 동안 1.1.1.1 리졸버가 전 세계에서 응답하지 않았다. Cloudflare는 많은 사용자에게 이것이 사실상 모든 인터넷 서비스를 쓸 수 없다는 뜻이었다고 밝혔다. UDP·TCP·DNS over TLS 조회가 영향을 받았고 도메인 이름으로 접속하는 DNS over HTTPS는 비교적 안정적이었다. 6월 6일 앞으로 쓸 다른 서비스의 서비스 토폴로지(어느 거점에서 IP 대역을 광고할지 정한 구성)를 준비하면서, 1.1.1.1 리졸버의 IP 대역이 실수로 그 구성에 함께 묶였다. 7월 14일 그 서비스 구성을 바꾸자 리졸버 대역을 광고하는 거점이 모든 곳에서 오프라인 거점 한 곳으로 줄었고, 전 세계에서 BGP 경로가 철회됐다. 이 변경은 카나리 배포를 거치지 않고 모든 데이터센터에 바로 퍼졌다. 22:20 설정을 되돌리자 트래픽이 약 77%까지 돌아왔다. 그사이 엣지 서버의 약 23%에서 필요한 IP 설정이 지워져 다시 설정하느라 22:54에야 정상이 됐다. Cloudflare는 공격이나 BGP 하이재킹과는 관계가 없는 내부 설정 오류라고 밝혔다.

게임 서버와 다른 유저는 멀쩡한데 일부 유저만 로그인·패치 서버에 접속 불가·무한 로딩이면 그 유저들이 쓰는 DNS를 의심한다. 이미 연결된 세션은 유지되고 새 접속만 실패하는 것이 특징이다. 유저에게 DNS 설정을 바꾸거나 서버 주소를 직접 조회해 보게 하면 바로 가려진다. 주 담당은 외부(DNS 운영자·통신사)이고 게임개발팀(클라이언트)이 이름 풀이 실패를 다른 오류와 구분해 안내하면 고객 지원에서 바로 판정할 수 있다. 원문

AWS 2025: AWS us-east-1 DynamoDB DNS 장애와 긴 복구

많은 게임이 서버·로그인·데이터를 퍼블릭 클라우드에 두므로, 게임도 함께 영향을 받는 유형의 인프라 장애다. 2025년 10월 19일 오후 11시 48분부터 20일 오후 2시 20분(태평양 서머타임)까지 북버지니아 리전에서 세 단계로 영향이 이어졌다. 20일 오전 2시 40분까지 DynamoDB API 오류가 늘었다. 오전 2시 25분부터 10시 36분까지 새 EC2 인스턴스 시작이 실패했다(일부 새 인스턴스의 연결 문제는 오후 1시 50분에 해소). 오전 5시 30분부터 오후 2시 9분까지는 일부 Network Load Balancer(NLB)의 연결 오류가 늘었다. DynamoDB의 DNS를 관리하는 자동화에 잠재된 경쟁 상태(race condition)가 있었다. 서로 다른 가용 영역에서 DNS 계획을 적용하는 실행기(DNS Enactor) 가운데 유난히 늦어진 하나가 오래된 계획으로 새 계획을 덮어썼다. 곧이어 다른 실행기의 정리 작업이 그 오래된 계획을 지워 리전 엔드포인트(dynamodb.us-east-1.amazonaws.com)의 DNS 레코드가 빈 값이 됐다. 자동화는 이를 고치지 못해 사람이 직접 복구해야 했다. EC2의 물리 서버 관리 시스템은 DynamoDB에 기대고 있어 그동안 물리 서버마다 유지하던 리스(lease)가 만료됐다. DynamoDB가 돌아온 뒤에는 리스를 다시 맺어야 할 물리 서버가 너무 많았다. 작업이 끝나기 전에 시간 초과되고 재시도 작업이 다시 쌓여 “혼잡 붕괴(congestive collapse)” 상태에 빠졌다. 새로 뜬 인스턴스의 네트워크 설정이 늦게 퍼지면서 NLB 헬스체크가 성공과 실패를 오갔고, 정상 노드까지 DNS에서 빠졌다가 돌아오기를 반복했다.

한 곳의 DNS 레코드 오류가 그 서비스에 기대는 다른 서비스로 번진다. 원인이 풀린 뒤에도 밀린 작업과 헬스체크 흔들림 때문에 복구가 몇 시간 더 걸린다. 게임 쪽에서 보면 이미 돌던 서버는 버텨도 새 서버를 못 띄워 오토스케일링이 멈추고, 헬스체크가 흔들리면 로드밸런서가 멀쩡한 서버를 빼는 일이 생긴다. 확인 신호는 클라우드 상태 페이지, 관리형 서비스 API 오류율, 인스턴스 시작 실패, 로드밸런서의 정상 대상 수다. 주 담당은 외부(클라우드 사업자)이고 인프라팀은 헬스체크 실패로 한꺼번에 빠지는 서버 수를 제한하고 다른 리전 대안을 준비한다. 원문

T4도구

렉 제보 가이드

게임개발팀·인프라팀이 원인을 찾는 데 가장 오래 걸리는 부분은 “언제, 어디서, 누가”를 알아내는 일입니다. 아래 항목을 채워 주면 로그와 그래프에서 그 순간을 바로 찾을 수 있습니다.

T5도구

용어 사전

게임개발팀·인프라팀과 대화할 때 자주 나오는 말들입니다. 검색창에 한글이나 영어로 입력해 보세요.

핑 Ping, RTT
내가 보낸 신호가 서버에 갔다가 돌아오기까지 걸린 시간(왕복). 게임에 표시되는 핑에는 서버 처리 대기 시간이 섞여 있기도 합니다.
지연 Latency
패킷이 출발해서 도착하기까지 걸리는 시간. 한쪽 방향만 말할 때가 많아 핑의 절반쯤입니다.
지터 Jitter
도착 간격의 흔들림. 평균 핑이 같아도 지터가 크면 화면이 뚝뚝 끊깁니다.
패킷 Packet
네트워크로 한 번에 보내는 데이터 묶음. 보통 최대 1,500바이트이고, 게임 업데이트는 수십~수백 바이트입니다.
패킷 손실 Packet loss
보낸 패킷이 도착하지 못하고 사라지는 것. TCP를 쓰는 게임은 1%만 돼도 몇 초~십여 초에 한 번씩 멈칫하는 것이 느껴지고, 보간·입력 중복 전송을 갖춘 UDP 게임은 몇 %까지 가려지기도 합니다.
대역폭 Bandwidth
회선이 1초에 보낼 수 있는 최대 데이터 양(Mbps). 얼마나 빨리 도착하느냐(지연)와는 다른 개념입니다.
틱 Tick
서버가 게임 상태를 한 번 계산하는 단위. 20틱 서버는 1초에 20번, 50ms마다 계산합니다.
틱레이트 Tick rate
1초에 틱을 몇 번 도는지. 높을수록 반응이 빠르지만 서버 비용과 전송량이 늘어납니다. 패킷을 보내는 횟수는 전송량을 아끼려고 틱레이트보다 낮게 잡기도 합니다.
틱 예산 Tick budget
한 틱을 끝내야 하는 시간 한도. 넘기면 다음 틱이 늦어져 틱 간격이 늘어납니다.
FPS Frames per second
1초에 화면을 몇 번 그리는지. 60FPS면 한 프레임에 16.7ms.
프레임 타임 Frame time
한 프레임을 그리는 데 걸린 시간. 평균 FPS보다 가끔 튀는 프레임이 체감에 더 중요합니다.
스냅샷 Snapshot
서버가 틱마다 보내는 “지금 게임 상태” 요약. 위치, 체력, 상태 등이 담깁니다. 대개 받는 쪽이 이미 가진 상태와 달라진 부분만 추려 보냅니다(델타 압축).
보간 Interpolation
받은 두 스냅샷 사이를 이어 그려 매끄럽게 보이게 하는 기술. 대신 조금 과거를 보여 줍니다.
보간 버퍼 Interpolation buffer
보간하려고 일부러 늦게 그리는 시간. 지터와 손실 한두 개를 흡수하는 여유 시간입니다. 보통 패킷 간격의 2배(1초에 20번 받으면 100ms)이고 지터가 커지면 스스로 늘리는 게임도 있습니다.
외삽 Extrapolation, Dead reckoning
새 패킷이 없을 때 마지막 속도로 앞으로 어디 있을지 추측해 그리는 기술. 틀리면 순간이동처럼 보여서 많은 게임이 0.25초 안팎까지만 추측하고 멈춥니다(소스 엔진 기본값 0.25초).
클라이언트 예측 Client-side prediction
서버 확인을 기다리지 않고 내 캐릭터를 먼저 움직여 보여 주는 기술.
서버 보정 Reconciliation
서버 결과가 오면 예측과 비교해 내 캐릭터 위치를 바로잡는 것. 서버가 확인한 위치에서 아직 확인 안 된 내 입력을 다시 적용해 계산합니다. 차이가 크면 고무줄처럼 보입니다.
지연 보상 Lag compensation
서버가 공격 판정을 할 때 공격자가 보던 과거 시점으로 되감아 맞았는지 확인하는 기술. 맞는 쪽이 억울하지 않게 되감는 폭에 상한을 둡니다. 경쟁 슈팅 게임은 0.2~0.25초 안팎이 흔하고 소스 엔진 기본값처럼 1초까지 되감는 경우도 있습니다.
권위 서버 Authoritative server
최종 판정은 서버만 한다는 설계. 치팅을 막지만 모든 결과가 서버 왕복을 거칩니다. 왕복을 기다리는 시간은 예측·선연출로 가립니다.
락스텝 Deterministic lockstep
모두가 입력만 주고받고 같은 턴에 똑같이 계산하는 방식. 입력에 일정한 지연을 붙이고 누구 하나의 입력이 늦으면 모두가 기다립니다.
서버 입력 버퍼 Server-side input buffer
서버가 사람마다 입력을 조금 모아 두었다가 한 틱에 하나씩 꺼내 쓰는 버퍼. 지터가 큰 사람도 남의 눈에 매끄럽게 보이지만 그 사람의 행동이 서버에서 확정되는 시점은 그만큼 늦어집니다.
리슨 서버 Listen server
플레이어 한 명의 PC가 게임을 하면서 서버 역할도 겸하는 방식. 방장은 핑이 0이지만 방장 회선이나 PC가 느리면 모두가 렉을 겪습니다.
페이즈 Phasing
같은 장소라도 퀘스트 진행도에 따라 NPC와 지형을 다르게 보여 주는 기능. 두 캐릭터의 진행도가 다르면 한쪽에만 NPC가 없는 게 정상입니다.
롤백 넷코드 Rollback netcode (GGPO)
상대 입력을 예측해 먼저 진행하고 실제 입력이 다르면 과거 프레임으로 되감아 다시 계산하는 방식. 격투 게임에서 많이 씁니다. DB의 롤백과는 다른 말입니다.
선입력 Input buffer, spell queue
쿨다운이나 동작이 끝나기 조금 전에 누른 다음 입력을 받아 두었다가 끝나는 순간 실행하는 것. 연계 사이에 왕복 시간이 끼지 않게 합니다.
선연출 Client-side feedback
서버 확인을 기다리지 않고 애니메이션·소리·이펙트를 먼저 재생하는 것. 데미지·보상처럼 확정이 필요한 결과만 서버 답을 기다립니다. 서버가 거절하면 보여 준 것을 되돌려야 합니다.
TCP Transmission Control Protocol
순서대로, 빠짐없이 전달하는 프로토콜. 잃어버린 패킷을 다시 받을 때까지 뒤 패킷을 게임에 넘기지 않습니다.
UDP User Datagram Protocol
아무 보장 없이 보내는 대로 전달하는 프로토콜. 기다림이 없는 대신 손실·순서는 게임이 직접 처리합니다.
신뢰성 UDP Reliable UDP (KCP, ENet…)
UDP 위에 필요한 만큼만 재전송·순서 보장을 직접 구현한 방식.
HOL 블로킹 Head-of-line blocking
앞의 하나가 막혀 뒤의 모두가 기다리는 현상. TCP 몰아치기의 원인입니다.
RTO Retransmission timeout
재전송 타이머. TCP가 패킷을 잃었다고 판단하고 다시 보내기까지 기다리는 시간. 리눅스는 핑 + 200ms 이상, 실패할수록 두 배.
Nagle 알고리즘 Nagle’s algorithm
앞서 보낸 데이터의 확인(ACK)이 올 때까지 작은 데이터를 모아 두었다가 한 번에 보내, 패킷 수를 아끼는 TCP 기능. 게임에서는 대개 꺼야 합니다.
TCP_NODELAY TCP_NODELAY
Nagle 알고리즘을 끄는 소켓 옵션. 작은 메시지를 즉시 보냅니다.
지연 ACK Delayed ACK
받았다는 확인을 조금 늦게, 다른 데이터와 묶어 보내는 기능. 리눅스는 보통 40ms(최대 200ms), 윈도우는 예전 버전이 200ms이고 요즘 버전은 40ms.
소켓 버퍼 SO_SNDBUF / SO_RCVBUF
OS가 소켓마다 두는 송신·수신 대기 공간의 크기. 너무 작으면 넘치고 너무 크면 오래된 데이터가 쌓여 기다립니다.
keepalive SO_KEEPALIVE
유휴 연결이 살아 있는지 확인하는 TCP 기능. 기본으로 꺼져 있고 켜도 기본값은 2시간 뒤에야 확인합니다.
RST TCP reset
연결을 그 자리에서 강제로 끊는 TCP 신호. 아직 못 보낸 데이터는 버려집니다.
하트비트 Heartbeat
게임이 직접 주기적으로 보내는 “살아 있음” 신호. 끊긴 연결을 감지하고 중간 장비의 연결을 유지하는 데 씁니다.
타임아웃 Timeout
이 시간 동안 응답이 없으면 실패로 보는 기준. 너무 짧으면 오판, 너무 길면 늦은 감지.
NAT Network Address Translation
공유기가 집 안 여러 기기를 공인 IP 하나로 내보내며 연결을 NAT 테이블에 기록하는 기능.
CGNAT Carrier-grade NAT
통신사가 여러 가입자에게 IP 하나를 나눠 주는 대규모 NAT.
MTU Maximum Transmission Unit
한 번에 보낼 수 있는 패킷 최대 크기. 보통 1,500바이트이고, VPN·PPPoE 구간에서는 더 작습니다.
버퍼블로트 Bufferbloat
장비가 대기열을 너무 크게 쌓아 두어 지연이 수백 ms로 늘어나는 현상.
SQM Smart Queue Management (fq_codel, CAKE)
대기열을 짧게 유지하고 흐름별로 공정하게 내보내는 공유기 기능. 버퍼블로트 해결책.
QoS Quality of Service
중요한 트래픽을 먼저 보내도록 우선순위를 주는 기능.
피어링 Peering
통신사끼리 망을 서로 연결하는 지점. 저녁에 붐비기 쉽습니다.
BGP Border Gateway Protocol
인터넷에서 어느 경로로 보낼지 통신사끼리 알려 주는 규칙. 바뀌면 경로와 핑이 달라집니다.
DDoS Distributed Denial of Service
많은 곳에서 대량의 트래픽을 보내 서비스를 마비시키는 공격.
스크러빙 센터 DDoS scrubbing center
DDoS 공격 때 서버로 가는 트래픽을 먼저 받아 공격을 걸러 내고 정상 트래픽만 넘겨 주는 방어 업체의 거점. 거점이 멀면 경로가 길어집니다.
방화벽 Firewall
허락된 연결만 통과시키는 장비나 프로그램. 연결을 세션 테이블로 추적합니다.
로드밸런서 Load balancer
들어오는 연결을 여러 서버에 나눠 주는 장비.
세션 테이블 Session table, conntrack
장비나 OS가 지금 열려 있는 연결을 추적하는 테이블. 크기에 한도가 있습니다.
마이크로버스트 Microburst
평균은 낮지만 1ms 이하의 아주 짧은 순간에 트래픽이 몰리는 현상.
NIC Network Interface Card
서버의 네트워크 카드.
링 버퍼 Ring buffer
NIC가 받은 패킷을 CPU가 꺼내 갈 때까지 담아 두는 버퍼. 정해진 개수의 슬롯을 돌려 쓰며 슬롯이 모두 차면 새 패킷은 버려집니다.
인터럽트 Interrupt
장치가 CPU에 “일이 생겼다”고 알리는 신호.
RSS Receive Side Scaling
받은 패킷을 여러 수신 큐로 나눠 여러 CPU 코어가 처리하게 하는 NIC 기능.
PPS Packets per second
초당 패킷 수. 게임 서버는 대역폭보다 이 숫자에서 먼저 한계에 닿곤 합니다.
커널 Kernel
운영체제의 핵심. 네트워크, 메모리, CPU 배분을 담당합니다.
backlog Listen backlog
서버가 아직 받아 가지 않은 새 접속 요청이 기다리는 대기열. 대기열이 차면 리눅스는 새 요청을 말없이 버리고 윈도우는 거절 응답을 보냅니다.
TIME_WAIT TIME_WAIT
연결을 먼저 닫은 쪽이 늦게 도착하는 패킷에 대비해 그 포트 조합을 잠시(리눅스 60초) 유지하는 상태.
CPU 스틸 Steal time
가상 머신이 CPU를 쓰려 했지만 물리 서버가 다른 가상 머신에 CPU를 주느라 기다린 시간. top의 st 값으로 봅니다.
CPU 스로틀링 CFS throttling
컨테이너가 정해진 주기(CFS period, 보통 100ms) 안에 CPU 할당량(quota)을 다 쓰면 다음 주기까지 강제로 멈추게 하는 것.
파일 디스크립터 File descriptor
프로세스가 연 파일·연결마다 붙는 번호(fd). 개수에 한도가 있습니다.
스레드 Thread
프로그램 안에서 독립적으로 실행되는 작업 단위. 여러 스레드가 동시에 실행될 수 있습니다.
컨텍스트 스위칭 Context switch
CPU가 실행 중인 스레드를 다른 스레드로 바꿔 끼우는 일. 비용이 듭니다.
락 Lock, Mutex
공용 데이터를 한 번에 한 스레드만 쓰게 막는 잠금.
데드락 Deadlock
스레드들이 서로 상대가 가진 락을 기다리며 영원히 멈춘 상태.
스레드 풀 Thread pool
미리 만들어 둔 워커 스레드 묶음. 모두 바쁘면 새 일은 기다립니다.
비동기 I/O epoll, IOCP, io_uring
입출력을 기다리지 않고 다른 일을 하다가 완료되면 알림을 받는 방식.
AOI Area of Interest
각 플레이어가 “볼 수 있는 범위”. 이 안의 변화만 보내 전송량을 줄입니다. 누가 범위 안에 있는지 따지는 비용을 줄이려고 보통 맵을 격자(그리드)로 나눠 가까운 셀만 봅니다.
브로드캐스트 Broadcast, fan-out
변화 하나를 그 변화가 보이는 여러 명에게 보내는 것. 모인 사람이 모두 서로를 보면 보낼 양이 인원의 제곱으로 늘어납니다.
GC Garbage collection
쓰고 버린 메모리를 자동으로 회수하는 기능. GC 중에 프로그램이 멈추기도 합니다.
힙 Heap
프로그램이 실행 중에 필요할 때마다 할당받아 쓰는 메모리 영역.
메모리 누수 Memory leak
다 쓴 메모리를 돌려주지 않아 사용량이 계속 늘어나는 버그. GC가 있어도 다 쓴 객체를 어딘가에서 계속 참조하고 있으면 생깁니다.
스왑 Swap, paging
램이 모자라 메모리 일부를 디스크에 옮겨 두는 것. 옮겨 둔 메모리를 다시 쓸 때는 램보다 1,000배 넘게 느립니다.
OOM 킬러 Out-of-memory killer
메모리가 바닥나면 리눅스가 메모리를 가장 많이 쓰는 프로세스를 골라 강제로 끝내는 기능. 컨테이너는 메모리 한도에 닿기만 해도 작동합니다.
캐시 미스 Cache miss
CPU 가까운 캐시에 데이터가 없어 느린 메모리까지 가야 하는 일.
IOPS I/O operations per second
디스크가 1초에 처리할 수 있는 읽기·쓰기 횟수. 클라우드 디스크는 돈을 낸 만큼 한도가 정해집니다.
fsync fsync
데이터가 디스크에 확실히 기록될 때까지 기다리는 명령. 보통 쓰기는 OS 메모리에 먼저 담겼다가 나중에 디스크로 내려가서, 그 사이 서버 전원이 꺼지면 사라질 수 있습니다. fsync는 안전하지만 느립니다.
버스트 크레딧 Burst credits
클라우드 디스크·서버가 잠깐 기준 이상 성능을 낼 수 있게 쌓아 두는 적립량. 바닥나면 기준 성능으로 떨어집니다.
인덱스 Index
DB의 색인. 없으면 테이블 전체를 읽어야 합니다.
풀 스캔 Full table scan
인덱스 없이 테이블의 모든 행을 확인하는 조회.
실행 계획 Query plan
DB가 쿼리를 어떤 순서로, 어떤 인덱스를 써서 풀지 정한 방법. 코드가 그대로여도 DB가 계획을 바꾸면 같은 쿼리가 갑자기 느려질 수 있습니다.
트랜잭션 Transaction
“전부 되거나 전부 안 되거나” 하나로 묶인 DB 작업. 거래는 반드시 트랜잭션으로 처리합니다. 끝날 때까지 고친 행을 잠가 두므로 짧을수록 좋습니다.
커넥션 풀 Connection pool
미리 맺어 둔 DB 연결 묶음. 모두 쓰이면 새 요청은 기다립니다.
핫 로우 Hot row
많은 요청이 동시에 고치려는 한 행. 잠금 경합의 원인.
복제 지연 Replication lag
복제본 DB가 주 DB를 따라가지 못하고 뒤처진 시간.
롤백 Rollback
저장이 취소되어 이전 상태로 돌아가는 것. 플레이어는 “아이템이 사라졌다”고 느낍니다.
캐시 Cache (Redis etc.)
자주 쓰는 데이터를 빠른 곳에 복사해 둔 것. DB 부하를 줄입니다.
체크포인트 Checkpoint
DB가 메모리에 모아 둔 변경분을 주기적으로 디스크에 몰아 쓰는 일. 그 순간 저장·조회가 잠깐 느려질 수 있습니다.
장애 전환 Failover
주 서버나 DB가 죽었을 때 예비 쪽으로 넘어가는 일. 넘어가는 동안 잠깐 저장이 안 되고 복제가 늦었다면 마지막 데이터가 사라질 수 있습니다.
MVCC Multi-version concurrency control
DB가 읽는 사람과 고치는 사람이 서로 막지 않도록 옛 버전을 잠시 보관하는 방식. 오래 열린 트랜잭션이 있으면 옛 버전이 쌓여 느려집니다.
캐시 스탬피드 Cache stampede
캐시가 한꺼번에 비어 요청이 원본(DB)으로 몰리는 현상.
게이트웨이 Gateway
클라이언트 연결을 받아 뒤쪽 게임 서버로 전달하는 중간 서버.
서킷 브레이커 Circuit breaker
실패가 계속되는 서비스 호출을 잠시 끊고 바로 실패로 처리해 연쇄 장애를 막는 장치. 얼마 뒤 한두 번 시험 삼아 불러 보고 복구됐으면 호출을 다시 허용합니다.
연쇄 장애 Cascading failure
한 곳의 장애가 호출 체인을 따라 다른 서비스로 번지는 것.
오토스케일링 Autoscaling
부하에 따라 서버 수를 자동으로 늘리고 줄이는 기능. 늘어나는 데 시간이 걸립니다.
워치독 Watchdog
서버가 멈췄는지 감시하는 타이머. 게임 루프가 정해진 시간(수 초~수십 초) 넘게 멈추면 상태 기록(덤프)을 남기고 서버를 강제로 끝내 다시 켜게 합니다.
이용률 Utilization
워커(CPU 코어·스레드·DB 커넥션처럼 요청을 처리하는 주체)가 바쁜 시간의 비율. 80~90%를 넘으면 대기가 급격히 늘어납니다.
p99 99th percentile
100번 중 99번은 이보다 빠르고 1번꼴로 이보다 느린 값. 평균보다 체감 렉을 더 잘 보여 줍니다.
V-Sync Vertical sync
화면 갱신 주기에 맞춰 프레임을 내보내는 기능. 화면 찢어짐은 없애지만 입력 지연이 생기고 FPS가 주사율 아래로 떨어지면 60과 30 사이를 오가며 뚝뚝 끊기기도 합니다.
가변 주사율 VRR, G-Sync, FreeSync
모니터가 프레임이 준비되는 때에 맞춰 화면을 바꾸는 기능. V-Sync에서 60과 30을 오가며 생기는 뚝뚝 끊김과 입력 지연을 줄여 줍니다.
안티치트 Anti-cheat
게임 해킹을 막는 보안 모듈. 주기적인 검사나 서버와의 하트비트가 실패하면 뚝뚝 끊김이나 접속 끊김을 만들기도 합니다.
오버레이 Overlay
메신저·녹화·FPS 표시 프로그램이 게임 화면 위에 그림을 덧그리는 기능. 게임의 그리기 과정에 끼어들어 뚝뚝 끊김을 만들 수 있습니다.
셰이더 컴파일 Shader compilation
그래픽 효과 프로그램을 GPU용으로 변환하는 작업. 미리 해 두지 않으면 처음 볼 때 화면이 멈칫합니다. 그래픽 드라이버를 업데이트하면 저장해 둔 결과가 무효가 되어 다시 합니다.
메인 스레드 Main thread, Game thread
게임 규칙 계산과 화면 준비를 차례로 처리하는 게임의 중심 스레드. 여기서 오래 걸리는 일이 하나라도 있으면 그동안 화면이 멈춥니다.
타이머 해상도 Timer resolution
운영체제가 잠든 프로그램을 깨워 줄 수 있는 가장 짧은 간격. 윈도우 기본값은 15.6ms라, 프로그램이 따로 바꾸지 않으면 “1ms 뒤에 깨워 줘”도 늦게 깨어납니다.
발열 스로틀링 Thermal throttling
기기가 뜨거워지면 스스로 CPU·GPU 속도를 낮추는 보호 기능. 폰에서는 몇 분~수십 분 게임하면 흔히 일어납니다.
VRAM Video memory
그래픽카드에 달린 전용 메모리. 텍스처와 모델을 여기에 올려 두고 그립니다. 모자라면 PC 메모리와 느린 경로로 주고받느라 뚝뚝 끊깁니다.
넷그래프 Net graph
게임 화면에 핑·손실·FPS·틱을 실시간 그래프로 띄우는 개발·디버그 표시. 렉 제보 영상에 같이 찍히면 원인 찾기가 훨씬 쉬워집니다.
재전송률 Retransmission rate
보낸 TCP 패킷 중 다시 보낸 비율. 공인된 기준은 없지만 서버 전체 평균이 0.1% 아래면 건강한 편이고 1%를 넘으면 많은 유저가 렉을 느끼기 쉽습니다. 평소 값보다 몇 배 늘었는지도 함께 봅니다.
SACK Selective ACK
받는 쪽이 “이 구간은 받았고 이 부분만 빠졌다”고 자세히 알려 주는 TCP 기능. 여러 개를 잃어도 한 번에 복구할 수 있습니다.
RACK-TLP Recent ACK, Tail Loss Probe
시간을 기준으로 손실을 판단하고 한동안 ACK가 없으면 끝 패킷을 한 번 더 보내 복구를 앞당기는 TCP 기능. 최신 리눅스·안드로이드의 기본입니다. 윈도우는 10(1607)·서버 2016부터 TLP와 RACK이 기본이고 잃은 재전송까지 복구하는 새 RACK은 서버 2022부터입니다. SACK이 켜진 연결에서만 작동합니다.
불필요한 재전송 Spurious retransmission
잃지 않았는데 늦게 오거나 순서가 바뀌어 잃은 줄 알고 다시 보낸 것. 회선을 낭비하고 전송량을 괜히 줄입니다.
제로 윈도우 Zero window
받는 쪽 버퍼가 꽉 차 “잠깐 보내지 마”라고 알린 상태. 재전송처럼 보이지만 회선은 멀쩡합니다. 받는 쪽 프로그램이 데이터를 제때 읽지 못해 생깁니다.
thin stream Thin stream
게임처럼 작은 패킷을 드문드문 보내는 연결. 빠른 재전송 신호가 잘 모이지 않아 손실 때 오래 멈춥니다.
폴리서 Policer
정해진 속도를 넘는 패킷을 대기열에 넣지 않고 바로 버리는 속도 제한 방식. 대기열에 넣었다가 천천히 내보내는 방식은 셰이퍼라고 합니다.
페이싱 Pacing
보낼 패킷을 한꺼번에 쏟지 않고 시간에 고르게 나눠 보내는 것. 작은 버퍼가 넘치는 것을 막습니다.
ECN Explicit Congestion Notification
혼잡할 때 패킷을 버리지 않고 “혼잡함” 표시를 붙여, 보내는 쪽이 속도를 줄이게 하는 기능. 손실 없이 혼잡을 알립니다. 양쪽 끝과 붐비는 구간의 장비가 모두 지원해야 효과가 있습니다.
MSS Maximum Segment Size
TCP가 한 패킷에 담는 데이터의 최대 크기. 보통 1,460바이트이고, 터널 구간에 맞춰 줄이면 MTU 블랙홀을 막을 수 있습니다.
핸드오버 Handover
이동 중인 폰이 연결된 기지국을 바꾸는 것.
백분위수 Percentile (p50, p95, p99)
값을 작은 순서로 늘어놓았을 때 몇 %째에 오는 값. p50은 중앙값, p99는 100번 중 가장 느린 1번 근처 값입니다. 평균이 감추는 튐을 보여 줍니다.
꼬리 지연 Tail latency
대부분은 빠른데 가끔 생기는 긴 지연. 평균에는 거의 드러나지 않지만 유저가 렉으로 기억하는 부분입니다.
합성 측정 Synthetic monitoring
실제 유저 대신 측정용 기기·서버가 정해진 곳에서 주기적으로 ping·traceroute 등을 보내 경로 품질을 재는 것. RIPE Atlas가 대표적인 공개 도구입니다.
집계 간격 Aggregation interval
그래프의 점 하나가 몇 초·몇 분의 값을 합친 것인지. 간격이 길수록 짧은 튐이 평균에 섞여 옅어집니다.
사후 분석 Postmortem
장애가 끝난 뒤 무슨 일이 있었고 왜 생겼으며 무엇을 바꿀지 정리한 글. 비난보다 재발 방지를 목적으로 씁니다.
C-state CPU idle state
CPU가 쉴 때 들어가는 절전 상태. 깊은 상태일수록 전기를 아끼지만 다시 깨어나는 데 시간이 걸립니다.
라이브 마이그레이션 Live migration
클라우드가 호스트 점검 같은 이유로 실행 중인 가상 머신을 다른 호스트로 옮기는 것. 옮기는 순간 잠깐 멈출 수 있습니다.
SNAT Source NAT
나가는 패킷의 출발지 주소를 공인 주소로 바꾸는 NAT. 공인 주소 하나가 쓸 수 있는 포트 수에 한도가 있어, 다 쓰면 새 연결이 실패합니다.
NAT 게이트웨이 NAT gateway
사설망의 서버들이 인터넷으로 나갈 때 공인 주소 하나를 함께 쓰게 해 주는 클라우드 장치. 목적지별 동시 연결 수에 한도가 있습니다.
저궤도 위성 인터넷 LEO satellite internet
수백~수천 km 높이의 위성들로 연결하는 인터넷. 정지궤도 위성보다 지연이 훨씬 짧지만 연결하는 위성이 바뀔 때 지연이 튈 수 있습니다.
GeoIP IP geolocation
IP 주소로 국가·도시·통신사를 추정하는 데이터베이스. 틀리거나 오래된 항목이 있어 먼 지역 서버에 배정되는 원인이 되기도 합니다.
TLS 인증서 TLS certificate
서버가 진짜 그 서버임을 증명하는 전자 문서. 유효 기간이 있어 만료되면 암호화 연결이 실패해 접속할 수 없습니다.
프레임 생성 Frame generation
그래픽카드가 실제로 그린 프레임 사이에 예측한 프레임을 끼워 넣어 FPS를 높이는 기술. 화면은 부드러워지지만 입력에서 화면까지의 지연은 늘 수 있습니다.
T6도구

참고 문헌

백서의 수치·기본값·동작 설명의 근거입니다. 표준 문서(RFC), 커널·OS 문서, 클라우드·엔진·DB 공식 문서, 발표·논문 등 공신력 있는 자료만 모았습니다. 원인 카드와 각 장 끝의 “출처”에서도 같은 자료로 이어집니다. 버전이 바뀌면 기본값도 바뀔 수 있으니, 실제 적용 전에는 쓰는 버전의 문서를 확인하세요.

자료 616건, 발행처 83곳. 목록은 텍스트 판의 참고 문헌에 있습니다.