결과 화면에서 8초 뒤 다음 경기: Salmonholic 자동 다음 경기를 멈추게 하는 다섯 가지 조건
Salmonholic 0.22.1에 넣은 자동 다음 경기 기록. 첫 결과 8초, 그 뒤 6초 카운트다운을 붙이고, 입력·탭 숨김·광고·10초 자리 비움·무입력 두 판일 때 멈추게 한 이유와 검증 과정을 정리했다.

9월 28일 저녁에 나간 Salmonholic 0.22.1(커밋 20b93dc)에는 자동 다음 경기가 들어 있다. 경기가 끝나면 결과 화면의 “한 판 더” 버튼에 카운트다운이 붙고, 아무것도 하지 않으면 다음 경기로 넘어간다. 작업 이름은 RA7이다. 기능 자체는 숫자 하나 줄이는 타이머라서 짧게 끝날 줄 알았는데, 실제 코드의 대부분은 “언제 넘어가지 않아야 하나”를 정하는 데 들어갔다. 이 글은 그 조건들을 정리한 것이다.
결과 화면에서 손을 놓는 순간
같은 날 오후에 나간 0.22.0 커밋(2a20f16) 첫 줄에 이 시기의 출발점이 적혀 있다. CrazyGames 기본 출시 점수가 9월 25~27일 기준 데스크톱과 모바일 모두 15점 만점에 4점이었고, 그중 플레이 시간 항목이 1점이었다. 0.22.0은 첫 1분 보호와 적응형 품질로 경기 안쪽을 다뤘고, 41분 뒤에 커밋한 0.22.1은 경기와 경기 사이를 다뤘다.
그전까지 결과 화면은 사람이 버튼을 눌러야만 다음으로 갔다. 표지가 카운트다운이 붙기 전의 결과 화면이다. 보상과 다음 목표, 내일 출석 미리보기까지 볼 것이 많지만, 그걸 다 읽은 뒤 “한 판 더”를 누르는 것은 온전히 사람 몫이었다. 경기 중에 죽으면 관전 화면으로 넘어가고, 거기서 빠져나오는 건너뛰기 버튼이 있었다.
0.22.1에서 바꾼 것은 세 가지다.
| 상황 | 0.22.1 이전 | 0.22.1 |
|---|---|---|
| 결과 화면 | “한 판 더”를 눌러야 시작 | 첫 결과 8초, 그 뒤 6초 카운트다운 후 자동 시작 |
| 경기 중 사망 | 관전 화면의 건너뛰기 버튼 | 건너뛰기 자리에 “다음 경기” 버튼을 바로 표시 |
| 설정 | 없음 | “다음 경기 자동 시작” 켜기/끄기, 기본 켜짐 |
첫 결과만 8초로 둔 것은 처음 보는 화면이라 읽을 것이 더 많기 때문이다. 사망 직후의 “다음 경기” 버튼은 누르면 결과 확정, 보상 처리, 방 나가기를 기존 경로 그대로 거친다. 누르지 않으면 예전처럼 관전이 이어지고, 남은 사람들의 서버 경기는 건드리지 않았다.
넘어가면 안 되는 다섯 순간
자동으로 넘어가는 기능에서 가장 나쁜 경우는 사람이 화면을 보지 않는데 경기가 시작되는 것이다. 자리에 없는 사람의 고양이가 경기장에 서 있게 되고, 돌아온 사람은 내가 시작하지 않은 경기를 보게 된다. 그래서 정책 파일 auto_continue.gd에 멈춤 조건을 모았다.
0.22.1의 정책을 그림으로 옮겼다. 세 번째 줄의 3초는 예시로 고른 시점이다.
- 결과 화면에서 입력이 있을 때. 탭, 키, 마우스 휠, 터치 끌기, 게임패드 입력이 들어오면 카운트다운을 끝낸다. 순위표를 스크롤하거나 캐릭터 선택 창을 연 사람을 경기로 끌고 가지 않기 위해서다. 다시 세지 않고 수동 대기로 바뀐다.
- 탭이 숨겨졌거나 페이지에 초점이 없을 때. 남은 시간이 줄지 않는다.
- 광고 요청이나 재생, SDK 일시정지 중일 때. 역시 시간이 멈춘다. 광고 요청 직전과 광고가 끝난 콜백 직후에 조건을 한 번 더 확인하고, 광고 도중 홈으로 가거나 취소한 자동 요청은 다음 경기를 열지 않는다.
- 10초 넘게 자리를 비웠을 때. 돌아와도 자동으로 넘어가지 않는다. 초점이 돌아온 것만으로는 이 상태가 풀리지 않고, 실제 입력이 있어야 풀린다.
- 자동으로 들어간 경기 두 판을 연달아 입력 없이 마쳤을 때. 보상은 평소대로 처리하고 타이틀에 머문다. 세 번째 자동 경기는 없다.
다섯 번째 조건의 판단은 결과 화면에 들어올 때 한 번에 한다.
func begin_results(enabled: bool) -> bool:
if match_auto and not match_input:
idle_auto_matches += 1
else:
idle_auto_matches = 0
match_auto = false
result_count += 1
remaining = 8.0 if result_count == 1 else 6.0
cancelled = not enabled or afk or idle_auto_matches >= 2
active = not cancelled
return idle_auto_matches >= 2
직전 경기가 자동으로 시작됐고 그 경기에서 입력이 한 번도 없었으면 무입력 횟수를 하나 올린다. 사람이 직접 시작한 경기이거나 한 번이라도 조작했으면 0으로 돌아간다. 사람이 자리에 있으면 계속 이어지고, 자리를 떠났으면 두 판 안에 멈춘다.
엔진이 멈춘 동안의 시간을 누가 재나
네 번째 조건은 생각보다 까다로웠다. 브라우저는 숨겨진 탭의 렌더링 루프를 멈춘다. Godot 쪽 코드도 같이 멈추니, 엔진 안에서 흐르는 시간만으로는 “얼마나 오래 비웠나”를 알 수 없다. 정책의 타이머도 한 프레임에 최대 0.25초까지만 줄이게 해 두었다.
그래서 시간 기록은 페이지의 자바스크립트에 맡겼다. 초점을 잃은 시각을 적어 두고, 돌아왔을 때 그 차이가 10초를 넘으면 자리 비움 표시를 남긴다.
const sync = () => {
const away = document.hidden || !document.hasFocus();
if (g.since && Date.now() - g.since > 10000) g.afk = true;
if (away && !g.since) g.since = Date.now();
if (!away) g.since = 0;
};
window.addEventListener('blur', sync);
window.addEventListener('focus', sync);
document.addEventListener('visibilitychange', sync);
엔진은 1초에 10번 이 상태를 읽어 정책에 넘기고, 자동 진입 직전에 한 번 더 읽는다. 브라우저 이벤트는 탭이 숨겨진 동안에도 기록이 남기 때문에, 엔진이 멈춰 있던 시간도 놓치지 않는다. 이 표시는 실제 입력이 들어올 때만 지운다.
검증과 계측
QA 기록(production/qa/ra7-2026-09-28/README.md)에 따르면 그날 맥에서는 헤드리스 검사만 돌렸다. 실제 Godot 흐름 검사는 8초/6초, 한 번만 발동, 입력과 휠, 숨김, 초점, 광고, 자리 비움 뒤 타이틀 대기, 설정 저장과 화면 재구성, 수동/자동 시작 흐름을 모두 통과했다. 문서 초점 추적 코드는 노드 가상 환경에서 따로 돌렸다. 결과 화면 기존 회귀 72개 조합도 통과했고, 고정 시드 경기 결과(골든)는 기준 파일을 다시 만들지 않고 그대로 맞았다. 시뮬레이션은 건드리지 않았다는 뜻이다.
버튼 글자 폭도 쟀다. “다음 경기까지 %d초…” 문구가 9개 언어에서 121~192px이었고, 가로 화면 버튼에 허용한 폭은 224px이다. 한국어는 143px, 가장 긴 것은 러시아어였다.
브라우저 확인은 다음 날 9월 29일 0.24.2 QA에서 했다. iPhone 13과 Pixel 7 크기로 에뮬레이션한 세로·가로 네 가지 화면에서 8/6초 자동 재경기와 무입력 두 판 제한이 확인됐다. 다만 이 항목의 다른 부분이 대체 검사로 남아 판정은 “부분 통과”로 적혀 있다.
마지막으로 재시작 이벤트에 replay_kind 값을 붙였다. 수동이면 manual, 자동이면 auto다. 웹 수집 서버는 이 두 값만 받고, 그 밖의 값이나 메일 주소처럼 생긴 문자열은 버리는 것까지 시험했다. 쿠키 없이 무엇을 모으는지는 텔레메트리 글에 적었다. 자동과 수동의 비율은 아직 기록에 정리된 수치가 없어서 여기에는 적지 않는다.
정리
| 항목 | 값 |
|---|---|
| 카운트다운 | 첫 결과 8초, 그 뒤 6초 |
| 시간이 멈추는 경우 | 탭 숨김, 초점 없음, 광고·SDK 일시정지 |
| 자동 진행을 끄는 경우 | 결과 화면 입력, 10초 넘는 자리 비움, 무입력 자동 경기 두 판, 설정 끄기 |
| 사망 직후 | “다음 경기” 버튼 즉시 표시 |
자동 다음 경기를 넣으면서 배운 것은, 사람을 붙잡는 기능일수록 놓아주는 규칙이 더 길어진다는 점이다. 결과 화면에 무엇이 나오는지는 결과 화면의 코인과 점수 글에, 같은 주에 기본 모드를 바꾼 실험은 기본 모드 실험 글에 정리했다. 카운트다운은 Salmonholic에서 한 판 끝나면 바로 볼 수 있고, 설정에서 끌 수도 있다.


