표에 없는 라운드가 세 개 있었다 — 유머 리포트 15편 라운드 회계 감사
칼라톤 AI 유머 배틀의 공개 시즌 리포트는 한 장에 같은 사실을 네 번 적는다. 맨 위 배지가 "25라운드"라고 말하고, 리더보드의 '우승' 열에 모델별 승수가 들어가고, 같은 행의 '총점'과 '평균'이 나눗셈 한 번으로 그 모델이 뛴 라운드 수를 되돌려 주고, 맨 아래 '전체 라운드 우승 코멘트' 표가 라운드를 한 줄씩 깔아 놓는다. 네 자리가 같은 시즌을 말하니 네 숫자는 같아야 한다.
대개는 같다. 그런데 앞선 칼럼 두 편이 지나가듯 같은 흔적을 남겼다. 리그 규모 회계는 챔피언 표의 '출전' 칸에 59/58 · 31/30 · 26/25를 적었다. 뛴 라운드가 시즌 라운드보다 하나 많다는 뜻이다. 두 점수 눈금은 각주에 "시즌 17은 표 30행인데 우승 수 31"이라고 적었다. 둘 다 증상을 적었을 뿐 세어 보지는 않았다.
그래서 이번에는 그것만 센다. 15편 전수에서 네 숫자를 각각 읽고, 어긋난 자리를 전부 찾고, 어긋남이 어느 라운드인지 어느 모델의 승수인지까지 좁힌다. 결론을 먼저 적으면 이렇다. 표에 없는 라운드는 세 개다. 그리고 표에서 비어 있는 번호는 다섯 개인데, 그 다섯 중 둘만 그 세 개에 해당한다. 비어 있는 번호와 숨은 라운드는 다른 것이다.
방법 — 한 시즌의 라운드 수를 네 번 센다
집계 대상은 저장소에 올라온 유머 리그 국문 리포트 15편(시즌 1·2·3·5·7·9·11·13·15·17·19·21·23·26·27, 발행일 2026-06-20~09-29)과 같은 시즌의 영문 15편이다. 외부 API를 쓰지 않고 HTML을 직접 파싱해 시즌마다 네 가지를 읽었다.
① 배지 — 히어로 영역의 "N라운드" 숫자.
② 표 — '전체 라운드 우승 코멘트' 표의 행 수, 그리고 각 행의 R 번호.
③ 우승 합 — 리더보드 '우승' 열 다섯 값의 합. 한 라운드에 우승자가 한 명이면 이 합이 곧 라운드 수다.
④ 최대 출전 — 리더보드의 총점 ÷ 평균. 모델이 채점받은 라운드 수가 복원되고, 그중 최댓값이 시즌 라운드 수의 하한이다.
④의 복원이 믿을 만한지부터 확인했다. 15편 × 5행 = 75행 전부에서 총점÷평균이 정수와 0.055 이내로 맞았고, 그렇게 얻은 정수를 분모로 다시 계산한 승률이 75행 모두 리포트 표기값과 소수점 첫째 자리까지 일치했다. 즉 리포트의 '승률' 열은 그 모델이 뛴 라운드 수를 분모로 쓰고, 우리는 그 분모를 지면에서 되읽을 수 있다. 이 복원 자체는 앞선 칼럼에서 쓴 방법 그대로다.
영문판도 같은 방식으로 읽어 대조했다. 배지의 라운드·총 코멘트, 표의 행 수와 R 번호 집합, 우승 합, 총점·평균이 15편 전부 국문과 일치했다. 아래의 어긋남은 번역이나 표시 단계에서 생긴 것이 아니라 두 언어판이 함께 물려받은 값이라는 뜻이다.
결과 ① — 배지와 표는 같은 증인이다
먼저 ①과 ②. 15편 전부에서 배지의 라운드 수와 표의 행 수가 정확히 같다. 90/90, 130/130, 87/87 … 25/25. 한 편도 어긋나지 않는다.
좋은 소식처럼 보이지만 실은 그 반대다. 두 숫자가 항상 같다는 것은 둘이 서로를 검증하지 못한다는 뜻이다. 리포트 생성기(aihumor-data-fetcher.js)는 라운드를 status = 'PUBLISHED' 조건으로 긁어 와 그 개수를 배지에 찍고, 같은 묶음으로 표를 만든다. 공개 상태가 아닌 라운드는 두 자리에서 동시에 빠진다. 배지를 믿고 표를 세는 독자는 영원히 같은 답을 얻는다.
결과 ② — 리더보드의 두 열은 775라운드를 말한다
③과 ④는 다른 곳에서 온다. 리더보드는 라운드를 세지 않고 모델별 원장(humor_season_competitors)의 누적값을 그대로 찍는다. 공개 상태로 걸러진 묶음이 아니다.
그래서 먼저 ③과 ④가 서로 맞는지 봤다. 15편 전부에서 '우승 열의 합'과 '총점÷평균의 최댓값'이 같은 정수를 가리켰다. 두 열은 계산 경로가 다르므로(한쪽은 승수 합, 한쪽은 점수 나눗셈) 이 일치는 우연이 아니다. 라운드마다 우승자가 정확히 한 명이고, 적어도 한 모델은 모든 라운드에 출석했다는 뜻이다. 이제 이 값을 '원장 라운드 수'라 부르겠다.
15시즌 합계로 보면 표는 772행이고 원장은 775라운드다. 세 라운드가 지면에 없다. 시즌별로는 이렇다.
| 시즌 | 배지 라운드 | 표 행 | 표의 R 범위 | 비어 있는 번호 | 우승 합 | 최대 출전 | 숨은 라운드 |
|---|---|---|---|---|---|---|---|
| 시즌 1 | 90 | 90 | R3~R92 | R1·R2 | 90 | 90 | 0 |
| 시즌 2 | 130 | 130 | R1~R131 | R125 | 130 | 130 | 0 |
| 시즌 3 | 87 | 87 | R1~R87 | — | 87 | 87 | 0 |
| 시즌 5 | 59 | 59 | R1~R59 | — | 59 | 59 | 0 |
| 시즌 7 | 59 | 59 | R1~R59 | — | 59 | 59 | 0 |
| 시즌 9 | 58 | 58 | R1~R58 | — | 59 | 59 | 1 |
| 시즌 11 | 59 | 59 | R1~R59 | — | 59 | 59 | 0 |
| 시즌 13 | 56 | 56 | R1~R56 | — | 56 | 56 | 0 |
| 시즌 15 | 19 | 19 | R1~R19 | — | 19 | 19 | 0 |
| 시즌 17 | 30 | 30 | R1~R31 | R27 | 31 | 31 | 1 |
| 시즌 19 | 25 | 25 | R2~R26 | R1 | 26 | 26 | 1 |
| 시즌 21 | 25 | 25 | R1~R25 | — | 25 | 25 | 0 |
| 시즌 23 | 25 | 25 | R1~R25 | — | 25 | 25 | 0 |
| 시즌 26 | 25 | 25 | R1~R25 | — | 25 | 25 | 0 |
| 시즌 27 | 25 | 25 | R1~R25 | — | 25 | 25 | 0 |
| 합계 | 772 | 772 | — | 5자리 | 775 | 775 | 3 |
어긋나는 시즌은 셋이다. 시즌 9 · 시즌 17 · 시즌 19, 각각 정확히 한 라운드씩. 나머지 열두 편에서는 네 숫자가 전부 같다.
결과 ③ — 숨은 라운드의 우승자까지 좁혀진다
어긋남이 한 라운드라면, 그 라운드의 우승자는 리더보드에 이미 한 표로 들어 있다. 그래서 표의 행을 모델별로 세어 리더보드의 '우승' 열과 맞춰 봤다. 15편 × 5행 = 75행 중 어긋난 행은 정확히 셋이고, 어긋난 시즌마다 한 모델만 한 표 많다.
| 시즌 | 한 표 더 가진 모델 | 표에서 센 승수 | 리포트 '우승' | 표 기준 승률 | 리포트 '승률' | 숨은 라운드의 위치 |
|---|---|---|---|---|---|---|
| 시즌 9 | Gemini | 19 | 20 | 32.8% | 33.9% | 마지막 행 뒤(R59 이후) |
| 시즌 17 | GPT | 12 | 13 | 40.0% | 41.9% | R27 — 표 중간 |
| 시즌 19 | Gemini | 7 | 8 | 28.0% | 30.8% | R1 — 표 앞 |
세 시즌의 숨은 라운드는 각각 Gemini · GPT · Gemini가 이겼다. 위치도 셋이 다르다. 시즌 17은 표가 R1~R31을 깔면서 R27을 건너뛴다. 시즌 19는 표가 R2에서 시작해 R1이 없다. 시즌 9는 R1~R58이 한 칸도 비지 않고 이어지는데 원장은 59라운드를 세므로, 숨은 라운드는 중간이 아니라 표의 끝 뒤에 있다. 번호만 보는 독자에게 시즌 9의 결손은 아예 보이지 않는다.
세 사례 모두 챔피언이나 열별 1위를 바꾸지는 않는다. 시즌 17 GPT는 그 한 표를 빼도 12승으로 1위, 시즌 9 Gemini는 19승으로 1위, 시즌 19에서 우승 수 1위는 9승의 Grok이고 Gemini는 한 표를 빼도 7승으로 2위다. 어긋남은 순위가 아니라 분모를 흔든다.
결과 ④ — 빈 번호는 두 종류다
여기서 이 감사의 핵심이 나온다. 표에서 비어 있는 R 번호는 15편 합쳐 다섯 자리다 — 시즌 1의 R1·R2, 시즌 2의 R125, 시즌 17의 R27, 시즌 19의 R1. 그런데 숨은 라운드는 셋뿐이다. 둘은 어디로 갔는가.
원장이 답한다. 시즌 1은 표가 R3에서 시작해 R92에서 끝나는데 원장 라운드 수도 90이다. 시즌 2는 표가 R1~R131에서 R125 하나를 건너뛰는데 원장도 130이다. 즉 시즌 1의 R1·R2와 시즌 2의 R125는 아무도 세지 않는다 — 배지도, 표도, 우승 합도, 출전 수도. 번호 체계에만 자리가 있고 그 자리에서 치러진 경기는 원장에도 없다. 반대로 시즌 17의 R27과 시즌 19의 R1은 원장이 한 표로 세고 있다.
번호만 빈 자리(3자리, 시즌 1·2) — 지면과 원장이 함께 비어 있다. 번호가 밀렸을 뿐 잃어버린 경기가 아니다.
숨은 라운드(3자리, 시즌 9·17·19) — 원장은 세는데 지면에 없다. 그중 둘은 번호가 비어 보이고(R27·R1), 하나는 번호로도 보이지 않는다(시즌 9).
그래서 빈 번호를 세는 것만으로는 둘을 가를 수 없다. 다섯 자리 중 어느 것이 잃어버린 경기인지는 리더보드를 봐야 알 수 있고, 시즌 9처럼 번호가 멀쩡한 결손은 리더보드만이 알려 준다. 라운드 수를 모수로 쓰는 집계가 이 구분을 건너뛰면 세 시즌에서 분모를 하나씩 틀린다.
결과 ⑤ — 세 번째 증인: 총 코멘트 배지
증거가 하나 더 있다. 상단 배지의 '총 코멘트'는 공개 라운드에 달린 코멘트 수이고, 리더보드의 출전 수(총점÷평균)를 다섯 모델에 걸쳐 더하면 원장이 센 채점 건수가 된다. 두 값을 15편에서 비교했다.
| 시즌 | 총 코멘트 배지 | 출전 수 합계(원장) | 지면 밖 코멘트 | 숨은 라운드 참석 |
|---|---|---|---|---|
| 시즌 9 | 289 | 294 | 5 | 5개 모델 전원 |
| 시즌 17 | 150 | 155 | 5 | 5개 모델 전원 |
| 시즌 19 | 120 | 124 | 4 | 4개 모델 |
| 나머지 12편 | 3,019 | 3,019 | 0 | — |
| 합계 | 3,578 | 3,592 | 14 | — |
열두 편에서 차이가 정확히 0이고, 어긋나는 세 편에서만 5·5·4다. 서로 다른 세 경로(우승 합 · 총점÷평균 · 코멘트 배지)가 같은 세 시즌을 가리키고 같은 크기를 말한다. 그리고 그 크기가 '5개 모델 × 1라운드'라는 것은 숨은 라운드가 중단된 경기가 아니라 정상적으로 치러지고 다섯 모델이 전부 제출한 라운드였음을 뜻한다. 시즌 19만 4건이고, 그 시즌은 Grok이 26라운드 중 21라운드만 뛴 시즌이다. 리그 전체로 보면 공개 지면에 실리지 않은 채점 코멘트가 14건이다.
결과 ⑥ — 가장 깨끗한 사례는 시즌 17이다
시즌 17은 결장이 하나도 없는 시즌이다. 공개 눈금으로 30라운드 × 5모델 = 150슬롯에 코멘트 150건, 원장 눈금으로 31 × 5 = 155슬롯에 155건. 어느 쪽으로 세도 결장률 0.0%다. 그래서 다른 잡음이 전혀 섞이지 않은 채 분모 문제만 남는다.
| 모델 | 총점 | 총점÷30 | 총점÷31 | 리포트 '평균' | 우승÷30 | 리포트 '승률' |
|---|---|---|---|---|---|---|
| GPT | 2,299 | 76.63 | 74.16 | 74.2 | 43.3% | 41.9% |
| Gemini | 1,974 | 65.80 | 63.68 | 63.7 | 30.0% | 29.0% |
| Claude | 1,850 | 61.67 | 59.68 | 59.7 | 13.3% | 12.9% |
| DeepSeek | 1,465 | 48.83 | 47.26 | 47.3 | 6.7% | 6.5% |
| Grok | 1,338 | 44.60 | 43.16 | 43.2 | 10.0% | 9.7% |
다섯 행 전부 '리포트 평균'이 총점÷31과 맞고 총점÷30과는 1.4~2.5점 어긋난다. 승률도 다섯 행 전부 31을 분모로 쓴다(Claude 4÷31 = 12.9%, DeepSeek 2÷31 = 6.5%). 정리하면 시즌 17 리포트의 리더보드 열 전체가 그 페이지의 다른 어디에도 적혀 있지 않은 숫자 31로 나눈 값이다. 독자가 배지의 30이나 표의 30행으로 같은 계산을 하면 다섯 모델 모두 다른 값을 얻는다. 결장이 있는 시즌에서는 이 간극이 '누가 몇 라운드 빠졌나'로 설명되지만, 시즌 17에는 결장이 없으니 설명은 하나뿐이다.
결과 ⑦ — 과거 집계는 얼마나 틀렸나
이 어긋남이 이미 발행된 칼럼들의 숫자를 흔드는지 확인했다. 결론은 "거의 흔들지 않는다"인데, 그 이유가 중요하다.
9월 30일 리그 규모 회계는 15시즌을 772라운드 · 3,860슬롯 · 결장 282건(7.3%)으로 적었다. 원장 눈금으로 고치면 775라운드 · 3,875슬롯 · 결장 283건으로 결장률은 7.3%에서 7.3%로 움직이지 않는다. 배지의 라운드 수와 배지의 총 코멘트 수가 둘 다 공개 라운드만 세기 때문에 분자와 분모가 같이 하나씩 모자랐고, 그래서 비율이 살아남았다. 시즌별로 값이 바뀌는 곳은 시즌 19 하나다(5/125 = 4.0% → 6/130 = 4.6%). 시즌 17은 양쪽 눈금 모두 0.0%, 시즌 9는 양쪽 모두 0.3%다.
반면 같은 글의 '라운드당 총점' 열은 세 행에서 분모를 하나씩 틀렸다. 시즌 9 Gemini 74.4 · 시즌 17 GPT 76.6 · 시즌 19 GPT 82.3은 원장 분모로 고치면 73.1 · 74.2 · 79.2가 되고, 이 세 값은 각 리포트가 '평균' 열에 이미 찍어 둔 값과 같다. 그 글이 바로 옆 칸에 적어 둔 '출전 59/58 · 31/30 · 26/25'가 그 어긋남의 영수증이었던 셈이다. 10월 2일 두 점수 눈금이 쓴 '역산 채점 건수 488'은 시즌 15·17·19·21의 95 + 155 + 124 + 114로, 이미 숨은 라운드를 포함한 값이라 고칠 것이 없다.
요약하면 배지끼리는 서로 모순이 없고 리더보드끼리도 모순이 없다. 둘을 섞은 계산만 틀린다. 라운드 수를 공개 쪽에서 가져오고 점수를 리더보드에서 가져오는 조합이 세 시즌에서 조용히 어긋난다.
한계 — 이 감사가 말할 수 없는 것
첫째, 숨은 라운드의 내용은 모른다. 우리가 확인한 것은 그 라운드가 존재했고, 다섯(또는 네) 모델이 제출했고, 누가 이겼는지까지다. 주제가 무엇이었는지, 우승 코멘트가 어떤 문장이었는지, 몇 점이었는지는 공개 지면에 없다. 모델의 총점에는 그 점수가 섞여 있지만 총점과 평균만으로 한 라운드의 점수를 분리해 낼 수는 없다.
둘째, 왜 지면에서 빠졌는지는 공개본으로 가릴 수 없다. 리포트 생성기가 공개 상태가 아닌 라운드를 건너뛴다는 사실은 코드로 확인되지만, 그 라운드가 어떤 상태로 어떤 이유에 의해 그렇게 되었는지는 공개 리포트에 적히지 않는다. 운영 과정에서 내린 비공개 처리일 수도 있고 생성 실패일 수도 있다. 이 글은 "지면과 원장이 어긋난다"는 사실까지만 말한다.
셋째, 시즌 9의 위치는 추정이다. 표의 번호가 R1~R58에서 한 칸도 비지 않으므로 숨은 라운드의 번호는 58보다 크다는 것까지가 확정이고, 그것이 정확히 R59인지는 지면만으로 단정할 수 없다. 반면 시즌 17의 R27과 시즌 19의 R1은 번호가 비어 있으므로 위치가 확정된다.
넷째, '우승 합 = 라운드 수'는 15편에서 성립한 규칙일 뿐이다. 한 라운드에 공동 우승이 생기거나 우승자가 없는 라운드가 생기면 이 등식이 깨지고, 그러면 숨은 라운드 수를 이 방법으로 셀 수 없다. 15편에서는 우승 합과 최대 출전이 모두 일치해 그런 사례가 없었음을 확인했지만, 그것은 지금까지의 사실이고 규격이 아니다.
다섯째, 모집단이 15편이다. 유머 리그의 시즌 번호는 27까지 왔지만 공개 리포트는 홀수 시즌 위주로 15편이고, 시즌 4·6·8·10·12·14·16·18·20·22·24·25의 리포트는 없다. 발행되지 않은 시즌에서 같은 어긋남이 몇 번 더 있었는지는 알 수 없다. 즉 "세 개"는 공개된 15편 안에서 세 개다.
여섯째, 하이라이트 섹션은 이 문제의 증인이 되지 못한다. 15편의 '베스트 코멘트 하이라이트' 150건을 라운드 표와 대조했더니 150건 전부 표에 있는 행이었다. 하이라이트와 표는 같은 묶음에서 만들어지므로 하이라이트에 숨은 라운드가 올라오는 일은 구조적으로 없다.
그래서, 라운드를 셀 때 무엇을 보아야 하나
세 가지다. 첫째, 한 시즌의 라운드 수는 지면에 두 개 있다. 하나는 공개된 라운드 수(배지 = 표 행 수)이고 하나는 원장이 센 라운드 수(우승 합 = 최대 출전)다. 15편 중 12편에서 두 수가 같아서 하나처럼 보이지만, 같은 것이 아니다. 비율을 계산할 때는 분자와 분모를 같은 눈금에서 가져와야 한다 — 그것만 지키면 세 시즌의 어긋남은 결과를 흔들지 못한다. 실제로 결장률 7.3%가 그렇게 살아남았다.
둘째, 빈 번호는 증거가 아니라 단서다. 다섯 자리 중 둘만 잃어버린 경기이고, 잃어버린 경기 중 하나는 번호가 비어 있지도 않다. 번호의 연속성을 검사하는 것만으로는 셋 중 하나를 놓치고 셋 중 둘이 아닌 것을 집는다. 판정은 리더보드가 한다.
셋째, 리포트는 자기 자신을 검증할 재료를 이미 싣고 있다. 총점과 평균 두 칸이 나눗셈 한 번으로 분모를 되돌려 주기 때문에, 우리는 데이터베이스를 열지 않고 공개 HTML만으로 775와 772의 차이를 찾을 수 있었다. 숫자를 여러 자리에 중복해 적는 것은 지면을 낭비하는 일처럼 보이지만, 그 중복이 감사를 가능하게 한다. 가장 좋은 지면은 서로를 반증할 수 있는 숫자를 나란히 놓은 지면이다.
남은 숙제는 지면 쪽이다. 리포트가 "25라운드"라고 말할 때 그것이 어느 눈금인지 한 글자도 적지 않는다는 것이 이번 감사에서 확인한 유일한 설계상의 공백이다. 세 시즌에서 숨은 라운드가 순위를 바꾸지 않았다는 사실은 운이고, 다음에도 그럴 이유는 없다. 그 전에 라운드 배지가 어느 쪽을 세는지 지면에 적어 두는 편이 낫겠다고 생각한다. 다만 그것은 집계의 결론이 아니라 편집의 판단이므로 여기서 정하지 않고, 어긋남의 전수만 기록으로 남긴다.
집계 기준. 2026년 10월 8일(KST) 기준 저장소의 공개 AI 유머 시즌 리포트 전부 — 국문 15편(시즌 1·2·3·5·7·9·11·13·15·17·19·21·23·26·27, JSON-LD 발행일 2026-06-20~09-29)과 같은 시즌의 영문 15편. 외부 API를 쓰지 않고 HTML을 파싱해 ① 히어로 배지의 '라운드'·'참가 AI'·'총 코멘트' ② '전체 라운드 우승 코멘트' 표의 행 수·R 번호·우승 AI ③ 리더보드 5행의 총점·평균·우승·승률을 전수로 읽었다. '최대 출전'과 '출전 수 합계'는 총점 ÷ 평균을 정수로 반올림한 복원값이다 — 75행 전부에서 몫이 정수와 0.055 이내였고, 그 정수를 분모로 다시 계산한 승률이 75행 모두 리포트 표기값과 소수점 첫째 자리까지 일치해 검증했다. '숨은 라운드' = 리더보드 우승 열의 합 − 라운드 표 행 수. '지면 밖 코멘트' = 다섯 모델의 복원 출전 수 합계 − 총 코멘트 배지. 슬롯 = 라운드 수 × 5(참가 AI 수는 15편 모두 5). 영문 15편에서 배지·표 행 수·R 번호 집합·우승 합·총점·평균이 국문과 전수 일치함을 확인했다. 지면이 공개 라운드만 싣는다는 구조는 리포트 생성기 aihumor-data-fetcher.js의 라운드·코멘트 조회 조건(status = 'PUBLISHED')에서 확인했고, 리더보드는 모델별 누적 원장 테이블을 그대로 찍는다. 리포트는 시즌이 끝날 때마다 추가되므로 편수와 합계는 집계 시점 이후 달라진다. 점수는 심판 모델의 판정값이며 유머의 객관적 품질을 뜻하지 않는다.