게임 렉 백서 › 증상별로 찾기
멈춤: 원인 67가지와 담당
다른 말: 얼어붙음, 정지, 응답 없음
그림이 있는 원본 증상 사전으로 열기 →
화면 속 모든 것이 잠깐(0.5초~수 초) 멈췄다가 다시 움직입니다.
모두가 정지. 내 캐릭터만 예측으로 조금 움직이거나 제자리 달리기. 풀리면 밀린 움직임이 몰아치기나 순간이동으로 한꺼번에 따라옵니다.
서버가 통째로 멈췄거나(GC, 데드락, 동기 호출), 회선이 잠깐 끊겼거나, 내 PC가 멈췄습니다.
이 증상을 만드는 원인
L1 클라이언트 게임 프로세스
- 프레임 타임 스파이크: 한 프레임 계산이 평소보다 몇 배 오래 걸려 화면이 잠깐 멈춥니다. (게임개발팀·클라이언트 개발)
- 클라이언트 가비지 컬렉션: 쓰고 버린 메모리(가비지)를 회수하는 동안 게임 전체가 멈춥니다. 규칙적인 간격으로 뚝뚝 끊기는 것이 특징입니다. (게임개발팀·클라이언트 개발)
- 메인 스레드 동기 로딩·셰이더 컴파일: 처음 보는 지역·몬스터·이펙트를 그리기 직전에 파일을 읽고 셰이더를 만드느라 멈춥니다. (게임개발팀·클라이언트 개발)
- 저장장치가 느려 에셋 스트리밍이 밀림: HDD처럼 느린 저장장치에서는 오픈월드의 텍스처·모델을 읽는 속도가 이동을 따라가지 못해, 개체가 늦게 뜨거나 게임이 읽기를 기다리며 끊깁니다. (게임개발팀·클라이언트 개발)
- 게임 보안 모듈(안티치트) 검사: 해킹을 막으려고 게임과 함께 도는 보안 모듈이 주기적으로 검사합니다. 검사가 무겁거나 보안 서버와 주고받는 하트비트(주기적인 생존 확인 신호)가 늦으면 뚝뚝 끊기거나 접속이 끊깁니다. (게임개발팀·클라이언트 개발)
L2 클라이언트 OS·기기
- 와이파이 ↔ LTE·5G 전환: 집 밖으로 나가며 와이파이가 끊기고 LTE·5G로 바뀌면 내 IP 주소가 바뀌어 기존 연결이 무효가 됩니다. (게임개발팀·서버 개발)
- 클라이언트 메모리 부족·스왑: 브라우저 탭 수십 개와 게임을 함께 켜 두면 OS가 게임 메모리 일부를 디스크로 내보냅니다. (외부·외부)
- 그래픽 메모리(VRAM) 부족: 그래픽 옵션이 요구하는 메모리가 그래픽카드 메모리보다 크면, OS가 텍스처를 PC 메모리로 내보냈다가 다시 가져오느라 뚝뚝 끊깁니다. (게임개발팀·클라이언트 개발)
- NIC 절전·드라이버 문제: 랜카드·와이파이 칩이 패킷 사이에 절전 상태로 들어가면 다시 활성화되는 데 시간이 걸립니다. (외부·외부)
- 오버레이 프로그램 간섭: 메신저·런처·녹화·FPS 표시 프로그램이 게임 화면 위에 자기 UI를 덧그리려고 게임의 렌더링 과정에 끼어듭니다(후킹). 프레임마다 작업이 늘고 가끔 게임과 부딪혀 멈칫하거나 게임이 강제로 꺼집니다. (외부·외부)
L3 집 네트워크
L4 인터넷 회선
- BGP 경로 변경·수렴: 인터넷의 경로 정보가 바뀌어 다시 수렴하는 몇 초~몇십 초(드물게 몇 분) 동안 패킷이 유실됩니다. (인프라팀·네트워크 인프라)
- 회선 품질 불량: 단자 접촉 불량이나 낡은 선, 모뎀 이상은 꾸준한 손실과 주기적인 회선 끊김을 만듭니다. (외부·외부)
L5 데이터센터 네트워크 장비
- 네트워크 장비 장애 전환(페일오버): 라우터·방화벽 한 대가 고장 나 예비 장비로 전환(페일오버)되는 몇 초 동안 모두가 멈춥니다. (인프라팀·네트워크 인프라)
- MTU 불일치 (큰 패킷만 사라짐): 중간 구간의 MTU(한 번에 보낼 수 있는 크기)가 줄었는데 크기 초과 알림이 막히면, 큰 패킷만 계속 사라집니다. (인프라팀·네트워크 인프라)
L6 서버 네트워크 카드
- 클라우드 호스트 점검·라이브 마이그레이션: 클라우드 사업자가 물리 서버(호스트)를 점검할 때 가상 머신을 다른 호스트로 옮기거나(라이브 마이그레이션) 잠시 멈춥니다. 그동안 서버 전체가 멈추고 멈춘 시간이 길면 연결이 끊깁니다. (인프라팀·서버 인프라)
- NIC 드라이버·펌웨어 문제: 드라이버 버그나 기능 오동작으로 카드가 멈춰 재시작되는 동안 모든 송수신이 끊깁니다. (인프라팀·서버 인프라)
L7 서버 OS (커널)
- CPU 스틸 (가상 머신): 물리 서버(하이퍼바이저)가 가상 머신의 CPU 시간을 잠시 다른 가상 머신에 넘기는 동안(CPU 스틸) 게임 서버가 멈춥니다. (인프라팀·서버 인프라)
- 메모리 회수·컴팩션으로 인한 멈춤: OS가 큰 페이지(huge page)를 만들려고 메모리를 컴팩션하거나 여유 메모리를 회수하는 동안 프로세스가 멈춥니다. (인프라팀·서버 인프라)
L8 소켓과 프로토콜
- TCP HOL 블로킹: TCP는 순서를 지키려고 잃어버린 패킷 하나를 다시 받을 때까지 뒤에 도착한 패킷을 게임에 넘기지 않습니다. (게임개발팀·서버 개발)
- TCP RTO와 지수 백오프: 재전송이 또 실패할 때마다 기다리는 시간이 두 배로 늘어, 짧은 회선 끊김이 긴 멈춤이 됩니다. (게임개발팀·서버 개발)
- 느린 클라이언트로 인한 블로킹 전송: 회선이 느린 한 명의 송신 버퍼가 가득 찼는데 블로킹 방식(버퍼에 여유가 생길 때까지 호출이 반환되지 않는 전송)으로 보내면, 서버 스레드가 그 한 명을 기다립니다. (게임개발팀·서버 개발)
- SO_REUSEPORT 분배 쏠림: 같은 포트를 여러 프로세스가 나눠 받으면, 커널은 접속마다 주소 해시로 담당 프로세스를 정해 두고 바꾸지 않습니다. 담당 프로세스 하나가 멈추면 거기에 배정된 사람만 기다립니다. (게임개발팀·서버 개발)
- 윈도우 UDP 소켓의 WSAECONNRESET 오류: 윈도우 서버가 이미 떠난 클라이언트에게 UDP를 보내면 “포트 없음”(ICMP) 알림이 돌아옵니다. 그 알림 때문에 다음 수신 호출이 오류로 끝나는데 서버 코드가 이 오류를 소켓 자체의 고장으로 처리하면 그 소켓을 쓰는 모두가 영향을 받습니다. (게임개발팀·서버 개발)
L9 서버 게임 프로세스
- 락 경합: 여러 스레드가 같은 데이터를 쓰려고 락 하나를 기다리면, 스레드를 늘려도 한 번에 하나씩만 실행됩니다. (게임개발팀·서버 개발)
- 데드락: 두 스레드가 서로 상대가 잡은 락을 기다리면 영원히 멈춥니다. (게임개발팀·서버 개발)
- 게임 스레드의 동기 호출: 틱 도중 DB 응답이나 파일 쓰기를 기다리면, 그 시간만큼 서버의 게임 진행 전체가 멈춥니다. (게임개발팀·서버 개발)
- 타이머 동시 발동 몰림: 모든 몬스터 리스폰, 모든 버프 만료, 정각 보상이 같은 틱에 몰리면 그 틱만 수십 배 무거워집니다. (게임개발팀·서버 개발)
- 스레드 풀 고갈: 작업을 처리할 워커 스레드가 모두 느린 작업에 묶이면 새 요청은 무작정 기다립니다. (게임개발팀·서버 개발)
- 무한 루프·로직 폭주: 버그로 한 틱이 끝나지 않으면 서버가 멈추고 워치독이 강제로 재시작합니다. (게임개발팀·서버 개발)
- 밀집 지역 진입 시 스폰 폭주: 사람이 가득한 마을로 텔레포트하면, 서버는 새로 보이게 된 수백 명의 외형·장비·상태를 한꺼번에 보내야 합니다. (게임개발팀·서버 개발)
L10 메모리
- 서버 GC 전체 멈춤: Java·C# 서버가 가비지를 수집하려고 모든 스레드를 멈추는 동안(stop-the-world) 서버 전체가 멈춥니다. (게임개발팀·서버 개발)
- 스크립트 엔진의 GC 멈춤: C++ 서버라도 퀘스트·AI·스킬을 Lua 같은 스크립트로 돌리면, 스크립트 엔진의 GC가 도는 동안 그 존이 멈춥니다. (게임개발팀·서버 개발)
- 할당 폭주: 이벤트 중 임시 객체를 대량으로 만들면 GC가 평소보다 훨씬 자주 돕니다. (게임개발팀·서버 개발)
- 메모리 누수: 해제되지 않는 메모리가 조금씩 쌓이면 며칠 뒤 GC 폭주·스왑·강제 종료가 일어납니다. (게임개발팀·서버 개발)
- GC 스래싱 (힙 여유 부족): 살아 있는 데이터가 힙 한도에 가까워지면, GC가 돌아도 회수할 것이 거의 없어 GC가 쉬지 않고 반복됩니다. (게임개발팀·서버 개발)
- 스왑: 메모리가 모자라 OS가 일부를 디스크로 내보내면, 그 메모리를 쓸 때마다 1,000배 넘게 느린 디스크를 기다립니다. (인프라팀·서버 인프라)
L11 디스크
- 동기 로그 쓰기: 게임 스레드가 로그 한 줄마다 디스크 완료를 기다리면, 디스크가 바쁠 때 게임 진행도 같이 멈춥니다. (게임개발팀·서버 개발)
- IOPS 한도·대기열 포화: 디스크가 1초에 처리할 수 있는 요청 수를 넘으면 대기열이 길어져 지연이 폭증합니다. (인프라팀·서버 인프라)
- 서버의 지연 로딩: 서버가 던전·맵 데이터를 처음 요청받을 때 디스크에서 읽으면, 그 틱 동안 모두가 멈춥니다. (게임개발팀·서버 개발)
L12 데이터베이스
- DB 장애 전환: 주 DB가 죽어 예비 DB로 전환되는 동안 쓰기가 안 되고 복제되지 못한 마지막 데이터는 사라질 수 있습니다. (인프라팀·DB 인프라)
- 캐시 스탬피드: 인기 데이터의 캐시가 동시에 만료되면 수천 개 요청이 한꺼번에 DB로 몰립니다. (게임개발팀·서버 개발)
- Redis 느린 명령: Redis는 명령을 한 번에 하나씩 처리해서 느린 명령 하나가 그 뒤의 모든 요청을 막습니다. (게임개발팀·서버 개발)
L13 서버 구성과 운영
- 존 이동 (서버 간 이관): 다른 지역·던전에 들어갈 때 캐릭터 정보를 다른 서버로 넘기는 과정에서 지연과 실패가 생깁니다. (게임개발팀·서버 개발)
- 연쇄 장애: 한 서비스가 느려지면 그걸 부르는 서버들이 응답을 기다리며 묶이고 상관없는 기능까지 멈춥니다. (게임개발팀·서버 개발)
- 로그·모니터링 과부하: 장애가 나면 로그가 폭증하고 로그를 동기로 넘기는 서버는 로그 때문에 더 느려집니다. (게임개발팀·서버 개발)
동기화 설계
- 락스텝에서 가장 느린 플레이어 대기: 모두가 같은 턴을 함께 계산하는 구조에서는, 한 명의 입력이 늦으면 모두가 기다립니다. (게임개발팀·서버 개발)
- 호스트(방장) 구조: 한 플레이어의 PC가 서버 역할을 하면, 그 사람의 회선과 PC 성능이 모두의 체감을 정합니다. (게임개발팀·서버 개발)
일부에게만 생기는 문제
- 특정 캐릭터의 데이터가 비대함: 아이템·우편이 수천 개 쌓였거나 친구·차단 목록, 버프가 유난히 많은 캐릭터는 접속하고 저장하고 주변에 알릴 양이 남보다 몇 배 큽니다. 회선과 상관없이 그 캐릭터로만 느립니다. (게임개발팀·서버 개발)
TCP 재전송의 근본 원인
- 무선 구간 손실: 와이파이와 모바일망은 무선 구간에서 몇 번 재전송하다가, 그래도 안 되면 패킷을 버립니다. 버려진 패킷은 TCP가 한참 뒤에 다시 보냅니다. (외부·외부)
- 병목 대기열 넘침 (혼잡 손실): 공유기, 통신사 사이 연결 구간, 데이터센터 회선처럼 가장 좁은 곳의 대기열이 가득 차면 새로 오는 패킷을 버립니다. (인프라팀·네트워크 인프라)
- 송신 버스트로 얕은 버퍼 넘침: 서버가 틱마다 수천 명분 업데이트를 한순간에 몰아 보내면, 스위치의 작은 버퍼나 클라우드의 순간 한도가 1ms도 안 돼 넘쳐 일부가 버려집니다. (게임개발팀·서버 개발)
- 폴리서의 초과분 폐기: 통신사 요금제, 클라우드 인스턴스 한도, DDoS 방어 장비는 정해진 속도를 넘는 패킷을 대기열에 넣지 않고 즉시 버리기도 합니다. (인프라팀·네트워크 인프라)
- 물리 오류 (불량 선·광모듈·커넥터): 케이블 손상, 먼지 낀 광커넥터, 수명이 다한 광모듈은 비트 오류를 만들고 깨진 패킷은 장비가 조용히 버립니다. (인프라팀·네트워크 인프라)
- 듀플렉스 불일치: 한쪽은 자동 협상, 다른 쪽은 속도·듀플렉스를 고정해 두면 한쪽이 반이중으로 동작하며 부하가 걸릴 때마다 충돌로 패킷을 잃습니다. (인프라팀·네트워크 인프라)
- 수신 서버 호스트의 패킷 폐기: 패킷은 서버까지 왔는데 NIC의 링 버퍼(도착한 패킷을 잠시 담아 두는 버퍼)가 넘치거나, 커널의 수신 처리 코어가 포화되어 버려집니다. (인프라팀·서버 인프라)
- 방화벽·연결 추적의 폐기: 방화벽이나 리눅스 연결 추적(conntrack, 지나가는 연결을 테이블에 기록하는 기능)은 테이블이 가득 차거나, 연결 상태가 맞지 않는다고 판단하면 패킷을 버립니다. (인프라팀·네트워크 인프라)
- 중간 장비 처리 한도 초과 (방화벽·IPS·DDoS 방어): 방화벽, 침입 방지 장비(IPS), DDoS 방어 장비는 지나가는 패킷을 하나하나 검사합니다. 검사 능력을 넘는 순간부터 처리하지 못한 패킷을 버립니다. (인프라팀·네트워크 인프라)
- MTU 블랙홀 (큰 패킷만 반복 손실): 중간 구간이 받을 수 있는 크기가 작아졌는데 “너무 크다”는 알림(ICMP)이 막히면, 큰 패킷은 몇 번을 다시 보내도 계속 사라집니다. (인프라팀·네트워크 인프라)
- 연결 도중 NAT·로드밸런서 매핑 만료: 유휴 연결의 매핑(이 연결을 어디로 전달할지 기록한 항목)을 중간 장비가 지우면, 다음에 보내는 패킷은 전달되지 못합니다. 재전송만 반복하다 접속이 끊기거나, 장비가 연결 거부(RST)를 돌려보내 곧바로 끊깁니다. (게임개발팀·클라이언트 개발)
- 경로 변경·ECMP 불량 경로: 인터넷 경로가 바뀌는 몇 초 동안, 또는 여러 ECMP 경로 중 불량인 경로에 배정된 연결에서 패킷이 사라집니다. (인프라팀·네트워크 인프라)
- 지연 급등으로 인한 불필요한 재전송: 패킷은 사라지지 않고 잠깐 아주 늦게 도착했을 뿐인데, 그 지연이 RTO보다 길면 보내는 쪽이 손실로 판단해 재전송합니다. (외부·외부)
- RTO 설정이 환경과 맞지 않음: RTO 최소값을 너무 낮추면 조금만 늦어도 불필요한 재전송이 나고 기본값(200ms)은 게임 입장에서 너무 길어 한 번 잃을 때마다 오래 멈춥니다. (인프라팀·서버 인프라)
- thin stream의 느린 복구: 게임처럼 작은 패킷을 드문드문 보내면 “뒤따르는 패킷 3개”가 모이기 전에 RTO가 먼저 옵니다. 대용량 전송보다 같은 손실에 훨씬 오래 멈춥니다. (게임개발팀·서버 개발)
- 중간 장비의 TCP 옵션 제거: 일부 방화벽·가속 장비가 TCP 옵션을 지우거나 고치면, 여러 개를 잃었을 때 한 왕복에 하나씩만 복구하거나 윈도우(한 번에 보낼 수 있는 양)가 작아져 느려집니다. (인프라팀·네트워크 인프라)
- 제로 윈도우 (재전송처럼 보이는 멈춤): 받는 쪽 프로그램이 소켓을 제때 읽지 않아 버퍼가 가득 차면, 보내는 쪽은 전송을 멈추고 제로 윈도우 프로브만 보냅니다. 회선 문제가 아닙니다. (게임개발팀·클라이언트 개발)
그림이 있는 원본 증상 사전 보기