"게임이 끊겨요" 티켓 진단하기 ① — 프레임 드랍의 원인 4분류
CPU 바운드, GPU 바운드, GC 스파이크, 로딩 히치. 프레임 드랍은 원인 분류가 먼저입니다 — 분류마다 최적화 방향이 정반대이기 때문입니다.
- unity
- performance
- qa
"끊겨요" 티켓 진단 3부작 — ① 원인 4분류 · ② 계측 실전 · ③ 발생 순간 캡처 (③ 공개 예정)
성능 티켓은 버그 티켓 중에서도 재현이 가장 어렵습니다. "인벤토리 열면 끊겨요"라는 티켓을 받은 개발자가 인벤토리를 열어봅니다. 부드럽습니다. 개발자 PC가 QA PC보다 빠르니까요. 결국 티켓은 닫히고, 출시 후 리뷰에 "최적화 좀"이 달립니다.
이 시리즈는 그 티켓을 진단 가능하게 만드는 과정을 다룹니다. 첫 단계는 계측도 최적화도 아니고 분류입니다.
왜 분류가 먼저인가
"끊긴다"는 하나의 증상이지만 원인은 대체로 넷 중 하나이고, 넷의 처방은 서로 정반대입니다. GPU 바운드 게임에서 스크립트를 최적화하면 아무것도 좋아지지 않습니다. GC 스파이크 게임에서 그래픽 품질을 낮춰도 히치는 그대로입니다. 분류를 건너뛴 최적화는 방향 없는 삽질이 됩니다.
1. CPU 바운드 — 메인 스레드가 못 따라간다
스크립트(Update), 물리, 애니메이션, UI 레이아웃이 프레임 예산(60fps 기준 16.6ms)을 넘는 경우입니다.
시그니처: 프레임 타임이 전반적으로 높고, 특정 상황(적이 많을 때, UI가 복잡할 때)에서 비례해서 나빠집니다. 해상도를 낮춰도 변화가 없습니다 — 이게 GPU 바운드와 가르는 가장 빠른 판별법입니다.
2. GPU 바운드 — 그리는 쪽이 못 따라간다
드로우콜 과다, 오버드로우, 무거운 셰이더, 고해상도가 원인입니다.
시그니처: 해상도나 품질 설정을 낮추면 즉시 좋아집니다. CPU 프레임 타임은 여유가 있는데 화면은 끊깁니다 — CPU가 GPU를 기다리는 시간(Gfx.WaitForPresent 계열)이 길게 잡힙니다.
저희가 실제로 겪은 사례가 이 유형이었습니다. Windows에서만 보고된 스터터링을 저희 SDK의 캡처 부하로 의심했는데, 계측해 보니 SDK를 꺼도 동일했고 원인은 게임 자체가 GPU 바운드인 것이었습니다. 체감과 추측은 범인을 자주 틀립니다. 이 판정 과정은 2편에서 다룹니다.
3. GC 스파이크 — 주기적으로 한 번씩 크게 멈춘다
매 프레임은 멀쩡한데 몇 초에 한 번씩 수십 ms짜리 히치가 옵니다. 매 프레임 할당되는 관리 힙 메모리(문자열 연결, 클로저, LINQ, new 되는 컬렉션)가 쌓여 GC가 도는 순간입니다.
시그니처: 프레임 타임 그래프가 평평하다가 주기적인 바늘 모양 스파이크를 찍습니다. 스파이크 간격은 할당 속도에 반비례합니다 — 전투처럼 할당이 많은 상황에서 간격이 짧아지면 거의 확정입니다.
4. 로딩 히치 — 특정 순간에만 한 번 멈춘다
씬 전환, 에셋 로드, 오브젝트 최초 등장, 셰이더 첫 컴파일처럼 이벤트에 결합된 단발성 멈춤입니다.
시그니처: 주기성이 없고 재현 조건이 명확합니다. "이 보스가 처음 나올 때만", "이 맵 처음 진입할 때만". 두 번째부터는 안 끊긴다면(캐시·컴파일 완료) 거의 이 유형입니다. 셰이더 컴파일 히치는 빌드에서만 나고 에디터에서는 재현되지 않는 경우가 많아 "재현 불가"로 닫히기 특히 쉽습니다.
티켓에서 분류 힌트 읽기
| 티켓 표현 | 유력한 분류 |
|---|---|
| "전투만 들어가면 전반적으로 무거워요" | CPU 바운드 |
| "옵션 낮추니까 괜찮아졌어요" | GPU 바운드 |
| "몇 초에 한 번씩 컥컥 걸려요" | GC 스파이크 |
| "이 맵 처음 들어갈 때만 멈춰요" | 로딩 히치 |
물론 이 표는 정황 증거입니다. 확정하려면 계측이 필요하고, QA의 체감 표현을 계측 데이터로 바꾸는 방법이 다음 편의 주제입니다.
성능 티켓이 "재현 불가"로 닫히는 구조는 일반 버그와 같습니다 — 발생 순간의 증거가 남지 않았기 때문입니다. 무엇을 남겨야 하는지는 버그 리포트 3부작에서 다뤘습니다.