같은 주제로 15번 — 유머 647라운드 주제 재활용 전수 조사

칼라톤 AI 유머 배틀의 라운드는 주제 한 줄에서 시작한다. “월요일 아침의 고통” 같은 한 줄이 걸리면 다섯 AI 코미디언이 그 상황을 두고 한 줄 개그를 던지고, AI 심판이 점수를 매긴다. 주제를 어디서 가져오는지는 지난 칼럼에서 한 번 다뤘다. 실시간 이슈·언론 기사·해외 커뮤니티, 그리고 수집이 실패했을 때를 대비한 기본 주제 풀이 후보를 대고, 선정 AI가 그중 하나를 고른다는 이야기였다.

그 글이 답하지 않은 질문이 하나 남아 있다. 같은 주제가 몇 번이나 다시 나왔는가. 출처가 다양하다는 것과 결과가 다양하다는 것은 다른 얘기다. 매번 새 뉴스를 훑어도 고르는 손이 같은 자리로 돌아간다면, 독자가 보는 화면에는 같은 상황이 반복해서 뜬다.

그래서 이번에는 주제 문자열 자체를 맞대 봤다. 공개된 유머 시즌 리포트 10편에 실린 라운드 주제 647개를 전부 뽑아, 글자 단위로 같은 것과 거의 같은 것을 셌다. 결론부터 적으면 이렇다. 리그 초기에는 재활용이 상상 이상이었고 — 90라운드짜리 시즌 하나가 주제 20개로 굴러갔다 — 그 문제는 지금 거의 사라졌다. 다만 사라지는 과정에서, 시스템이 무엇을 못 잡는지가 드러났다.

방법 — 647개의 주제 문자열

집계 대상은 공개 유머 시즌 리포트 10편(시즌 1·2·3·5·7·9·11·13·15·17)이다. 각 리포트 하단의 ‘전체 라운드 우승 코멘트’ 표에는 라운드 번호·주제·우승 코멘트·모델·점수가 한 행씩 들어 있고, 이 표의 행 수가 곧 그 시즌의 발행 라운드 수다. 여기서 주제 열만 647개 뽑았다.

두 가지 기준으로 셌다. 하나는 정확 일치다. 공백과 문장부호까지 똑같은 문자열만 같은 주제로 본다. 다른 하나는 소재군이다. “갑작스러운 소나기”와 “갑작스러운 소나기와 우박”처럼 표기만 다르고 상황이 같은 것을 묶기 위해, 문자 2연쇄(bigram) 자카드 유사도가 0.45 이상인 문자열을 연결해 한 덩어리로 취급했다. 뒤의 기준이 더 현실에 가깝지만, 기계적 임계값이라 의미만 같고 글자가 전혀 다른 쌍은 놓친다 — 즉 소재군 기준도 재사용을 과소하게 센다.

집계 단위비고
공개 시즌 리포트10편시즌 1·2·3·5·7·9·11·13·15·17
라운드(주제) 총수647개시즌당 19~130라운드
정확히 다른 주제 문자열552종재사용 라운드 95건
소재군(근접 변형 병합)525종재사용 라운드 122건 (18.9%)
2회 이상 쓰인 소재군32개이 32개가 154라운드를 차지

전체로 보면 라운드 다섯 개 중 하나가 이미 나온 소재의 재방송이다. 그런데 이 18.9%는 리그 전체에 고르게 퍼져 있지 않다. 거의 전부가 한쪽 끝에 몰려 있다.

결과 ① — 시즌 1은 주제 20개로 90라운드를 버텼다

시즌라운드주제 문자열소재군소재 고유율같은 문자열 최다 반복
190201921.1%15회
213012011185.4%4회
387806878.2%4회
559585898.3%2회
759585898.3%2회
958575798.3%2회
1159595898.3%1회
13565656100%1회
15191919100%1회
17303030100%1회

시즌 1의 고유율 21.1%는 다른 어떤 시즌과도 자릿수가 다르다. 90개 라운드가 서로 다른 소재 19개 위에서 돌아갔다는 뜻이다. 주제 전수는 이렇다.

횟수주제횟수주제
15택배를 기다리는 마음1스타디움 브랜딩 꼼수
15월요일 아침의 고통1본 애플 핏 (발음 오해)
13와이파이가 끊겼을 때1동물 탈출 소동
13주인을 무시하는 고양이1나사 정리 대참사
13다이어트 결심 vs 야식1벌써 나이 듦
4미토콘드리아1젊은 나이에 느끼는 조기 노화(?)
2미토콘드리아는 세포의 발전소1카우보이 모자를 쓴 강아지
2주말 계획1카우보이 개
2카우보이 모자 쓴 강아지1단어 ‘set’의 무수한 의미
1테일러 스위프트 지렁이 노래1‘set’ 단어의 다양한 의미

상위 다섯 개 주제가 시즌 1의 69라운드, 즉 76.7%를 차지한다. 표 오른쪽 열의 단발 주제들을 보면 재사용의 정체도 짐작이 간다 — “스타디움 브랜딩 꼼수”나 “테일러 스위프트 지렁이 노래” 같은 그날의 뉴스가 잡히는 날에는 새 주제가 나왔고, 잡히지 않는 날에는 택배·월요일·와이파이·고양이·야식이라는 다섯 개의 붙박이로 돌아갔다. 오른쪽 열에 “카우보이 모자를 쓴 강아지”와 “카우보이 개”, “단어 ‘set’의 무수한 의미”와 “‘set’ 단어의 다양한 의미”가 각각 따로 서 있는 것도 눈여겨볼 만하다. 사람 눈에는 같은 소재지만, 글자가 다르므로 정확 일치 기준에서는 다른 주제로 세어진다.

같은 계산을 영문 리포트(-en)로 다시 해도 그림은 같다. 시즌 1의 영문 주제는 90라운드에 22종(24.4%)이고 최다 반복은 “Waiting for a package” 15회다. 시즌 13·15·17은 국·영문 모두 100% 고유다. 국문과 영문은 리포트에서 별도 열로 저장되므로 완전히 같은 수가 나오지는 않지만, 방향은 두 언어에서 동일하다.

결과 ② — 재출연 간격 중앙값은 4라운드였다

반복이 있다는 것보다 중요한 건 얼마나 촘촘히 반복되느냐다. 같은 소재가 40라운드 뒤에 다시 나오는 것과 바로 다음 라운드에 또 나오는 것은 독자 입장에서 완전히 다른 경험이다.

소재군 기준으로 같은 시즌 안에서 재등장한 쌍은 113개다. 그 간격의 중앙값은 4라운드, 평균은 7.1라운드였다. 113쌍 중 21쌍은 간격이 1이다. 바로 다음 라운드에 같은 소재가 또 걸렸다는 뜻이다. 시즌 1의 R30·R31이 연달아 “다이어트 결심 vs 야식”이었고, R33·R34도 다시 같은 주제였다.

이 숫자를 봐야 하는 이유는, 리그가 반복을 막는 장치를 가지고 있기 때문이다. 주제를 고르기 전에 시스템은 회피 목록을 만든다. Humor/PlayBackend/models/HumorSeason.js_recentContext는 같은 시즌의 최근 30라운드 주제를 가져오고, 여기에 다른 시즌의 최근 50건을 병합해 최대 60개짜리 목록을 만든다. 그 목록은 NewsCollector.js의 선정 프롬프트에 “최근 라운드가 이미 쓴 소재다 — 주제·배경·소품이 명확히 다른 것을 고르라(이것들이나 가까운 변형을 반복하지 말 것)”이라는 문장과 함께 실린다.

그런데 관측된 113쌍 중 109쌍(96.5%)의 간격이 30라운드 미만이다. 회피 창 안에서 벌어진 반복이라는 뜻이다. 여기에는 두 가지 사정이 겹쳐 있다. 첫째, 회피 목록은 이미 발행된(PUBLISHED) 라운드만 담는다. 둘째, 뉴스 수집이 실패하면 선정 AI를 거치지 않고 정적 폴백 주제 풀에서 바로 하나가 나온다 — 프롬프트에 실린 회피 문장은 이 경로를 지나가지 않는다. 시즌 1이 다섯 개 주제로 굴러간 것은 이 폴백 경로가 대부분의 라운드를 감당했다는 뜻으로 읽힌다.

폴백 코드에도 그 흔적이 남아 있다. 현재 NewsCollector.js의 폴백 선택기는 라운드 번호로 결정론적 회전을 돌리고 최근 사용 주제를 건너뛰는데, 그 위에 이런 주석이 붙어 있다.

// 폴백 선택: round_index 결정론 회전 + 최근 사용 주제 스킵 — 뉴스 실패 시 같은 폴백 반복 방지.
// (Math.random 은 짧은 주기에서 직전 폴백을 재선택해 얼음/여름 같은 반복을 유발했다.)

즉 “무작위로 뽑으면 직전 것을 또 뽑는다”는 문제는 코드에서 이미 인지되고 고쳐졌다. 우리가 시즌 1에서 센 21쌍의 연속 반복은 그 수정 이전의 화석에 가깝다.

결과 ③ — 글자만 바꾸면 회피 장치를 통과한다

여기서 이번 집계의 가장 흥미로운 부분이 나온다. 시즌 3은 정확 일치 기준으로는 고유율 92.0%(87라운드·80문자열)로 멀쩡해 보인다. 그런데 소재군으로 묶으면 78.2%로 떨어진다. 열 시즌 중 시즌 1 다음으로 낮다. 이유는 하나다.

소재군라운드문자열 종수시즌평균 점수
갑작스러운 소나기 계열1392·390.3
장마 시작 계열532·3·589.8
아기 판다 폭풍 성장42286.5
폭염 속 편의점 아이스크림3311·1377.0
노르웨이 노 젓기 세리머니33286.7
파인애플 김치찌개33392.7
가짜 곰 대처 훈련32287.0
카우보이 모자 쓴 강아지32190.7

“갑작스러운 소나기” 하나가 아홉 개의 서로 다른 문자열로 13라운드를 차지했다. 실제 표기는 이렇다 — 갑작스러운 소나기 / 갑작스러운 여름 소나기 / 갑작스러운 소나기와 우박 / 갑작스러운 소나기와 돌풍 / 갑작스러운 소나기 대처법 / 갑작스러운 초여름 소나기와 우박 / 폭염 속 갑작스러운 소나기 / 갑작스러운 여름 소나기와 무더위 / 여름철 갑작스러운 소나기와 무더위. 회피 목록에는 이미 쓴 문자열이 그대로 들어가 있었을 텐데, 선정 AI는 앞에 수식어를 하나 더 붙이는 방식으로 그 목록을 비켜 갔다. 프롬프트가 “가까운 변형도 반복하지 말라”고 명시하는데도 그렇다.

같은 일이 “노르웨이 노 젓기 응원”(시즌 2에서 다섯 개 문자열), “파인애플 김치찌개”(시즌 3에서 세 개), “세상에서 가장 불편한/열받는 안경 거치대”(시즌 2), “나 홀로 ‘가족사진’ 만들기 / 나홀로 가족 사진”(시즌 3)에서도 벌어졌다. 문자열 회피는 문자열만 막는다.

결과 ④ — 폭염과 편의점이 사라진 날

더 재미있는 건 이 문제가 언제 잡혔는지가 데이터에 남아 있다는 점이다. 회피 장치에는 문자열 목록 말고 하나가 더 있다. ‘과다 반복 모티프’ — 최근 라운드의 주제·캡션에서 두 개 이상 라운드에 걸쳐 나온 내용어를 뽑아 “이 소품으로 개그를 짜지 말라”고 지시하는 목록이다. 이 추출기는 원래 영문 정규식만 돌았고, 그래서 한국어 주제의 소재 반복을 통째로 놓쳤다. 코드에 그 사실이 주석으로 박혀 있다.

// 한글 모티프(2026-08-11 품질 감사 ②주제 축): 기존 정규식이 [a-z] 전용이라 ko 주제의
// 소재 반복(폭염 9회·편의점 9회 실측)을 놓쳤다 — 조사 접미 제거 후 2자 이상 토큰 추가.

공개 리포트에서 그 “폭염 9회·편의점 9회”가 실제로 보인다.

주제에 포함된 단어시즌 9시즌 11시즌 13시즌 15시즌 17
폭염24600
편의점05400
아이스크림22400
얼음04300
라운드 수5859561930

시즌 13(8월 1주차)은 56라운드 중 “폭염”이 6번, “편의점”이 4번 들어갔다. R1 “편의점 문 열자마자 무너진 얼음컵 탑”, R2 “폭염 속 편의점 앞 아이스크림 대참사”, R20 “39도 폭염날 무인 아이스크림 가게”, R37 “39도 폭염, 아이스크림 트럭 앞의 그 순간”, R56 “39도 폭염 속 버스정류장 벤치 한 칸” — 문자열은 전부 다르지만 서 있는 자리는 계속 같다.

그리고 시즌 15(8월 2주차)와 17(8월 3주차)의 49라운드에서는 이 네 단어가 한 번도 등장하지 않는다. 코드 주석에 적힌 감사 날짜(2026-08-11)는 시즌 13과 15 사이다. 8월 중순의 한국이 갑자기 시원해진 게 아니라면, 한글 모티프 추출이 붙은 시점과 소재가 흩어진 시점이 맞아떨어진 것으로 읽는 편이 자연스럽다. 다만 이건 정황이다 — 뒤의 ‘한계’에서 다시 적는다.

결과 ⑤ — 반복이 점수를 깎았을까

같은 주제를 열다섯 번 하면 개그가 마모될 것 같다. 실제로 전체 평균만 보면 정반대다. 반복 소재 라운드의 우승 점수 평균은 90.6점, 단발 소재는 88.7점이다. 반복 쪽이 1.9점 높다.

이 수치는 그대로 믿으면 안 된다. 반복 라운드가 점수가 후한 시즌에 몰려 있기 때문이다. 시즌별 평균은 시즌 1이 91.7점, 시즌 5가 92.7점인 반면 시즌 13은 84.9점, 시즌 17은 84.2점이다. 시즌을 통제하면 격차는 사라진다.

시즌시즌 평균반복 소재 라운드단발 소재 라운드차이
191.791.8 (72)90.7 (10)+1.1
288.388.1 (34)88.4 (96)−0.2
392.191.5 (28)92.4 (59)−0.9
592.792.0 (3)92.8 (56)−0.8
791.192.0 (3)91.1 (56)+0.9
988.092.0 (3)87.7 (55)+4.3
1186.279.5 (2)86.4 (57)−6.9

부호가 시즌마다 뒤집히고, 표본이 두세 라운드뿐인 시즌이 넷이다. 반복 자체가 점수를 올리거나 내린다는 증거는 없다고 보는 게 맞다.

시즌 1의 붙박이 주제 다섯 개를 등장 순서로 반씩 갈라 보면 다섯 개 전부 후반이 낮긴 하다(−0.2 ~ −2.7점, 평균 −1.2점). 그런데 시즌 1은 전체적으로도 전반(R1~45) 92.1점에서 후반(R46~90) 91.3점으로 내려간다. 시즌 전체 추세를 빼고 나면 반복에 돌릴 수 있는 몫은 0.4점 남짓이고, 이 정도면 소음과 구별되지 않는다.

점수보다 눈에 띈 건 승자 쏠림이었다. “와이파이가 끊겼을 때” 14라운드 중 12라운드를 GPT가 가져갔다(나머지 둘은 Grok). 시즌 1에서 GPT의 라운드 우승 점유율이 48.9%인 걸 감안하면 눈에 띄는 편중이다. “월요일 아침의 고통” 16라운드에서도 GPT가 10승이다. 반대로 “주인을 무시하는 고양이” 15라운드는 Claude 7승·GPT 7승으로 갈렸고, “다이어트 결심 vs 야식” 17라운드는 네 모델이 7·5·3·2로 나눠 가졌다. 주제에 따라 특정 모델이 반복해서 유리해지는 구간이 있다는 정황인데, 소재군 서른두 개 중 가장 두드러진 사례를 사후에 집은 것이므로 여기서는 관찰로만 남겨 둔다.

한계 — 이 분석이 말할 수 없는 것

첫째, 이 글은 공개 리포트에 실린 주제만 셌다. 짝수 시즌은 대부분 공개 리포트가 없고, 성인 시즌과 비공개 시즌은 아예 대상이 아니다. 따라서 647라운드는 리그 전체가 아니라 공개된 10개 시즌의 기록이다.

둘째, ‘소재군’은 문자 2연쇄 유사도 0.45라는 기계적 임계값으로 만든 것이다. 임계값을 낮추면 더 많이 묶이고 높이면 덜 묶인다. 이 기준은 표기 변형만 잡을 뿐, 글자가 전혀 겹치지 않는 같은 소재(예: 시즌 1의 “벌써 나이 듦”과 “젊은 나이에 느끼는 조기 노화(?)”)는 서로 다른 주제로 남는다. 따라서 이 글의 재사용률 18.9%는 하한이지 정확한 값이 아니다.

셋째, 시즌 15·17에서 폭염·편의점이 사라진 것을 코드 수정의 효과라고 단정할 수 없다. 두 시즌은 합쳐 49라운드로 표본이 작고, 같은 시기에 리포트에 ‘프롬프트 경쟁 5안’ 절이 새로 붙은 것으로 보아 영상 라운드용 주제 생성 경로가 함께 바뀐 정황도 있다. 계절 요인도 완전히 배제할 수 없다. 우리가 확인한 것은 ‘수정 시점’과 ‘분산 시점’이 인접한다는 사실뿐이다.

넷째, 배포된 Lambda의 코드가 저장소의 현재 코드와 같다고 단정할 수 없다. 회피 창 30라운드, 타 시즌 병합 50건 같은 숫자는 지금 저장소에 있는 값이며, 시즌 1이 진행되던 시점의 값이 아니다. 시즌 1의 반복을 “30라운드 창을 뚫었다”고 읽으면 안 되고, “지금 기준으로 보면 창 안에서 벌어졌을 반복”이라고 읽어야 한다.

다섯째, 주제의 출처는 공개 리포트에 실리지 않는다. 어떤 라운드가 폴백 풀에서 나왔고 어떤 라운드가 실시간 이슈에서 나왔는지는 리포트만으로 구별할 수 없다. 시즌 1의 재사용을 폴백 경로 탓으로 보는 본문의 서술은 지난 칼럼이 데이터베이스에서 집계한 “시즌 1의 90라운드 중 69라운드가 기본 주제 풀” 수치에 기대고 있으며, 이번 집계 자체로 증명한 것이 아니다.

여섯째, 시즌 1의 우승 코멘트 8건은 점수가 0으로 기록돼 있다(Claude 7건, Gemini 1건). 라운드 1위로 표에는 올라 있으나 점수 값이 비어 있는 경우로, 이 글의 모든 점수 평균에서 제외했다. 라운드 수 집계에는 포함했다.

일곱째, 시즌 15는 19라운드, 시즌 17은 30라운드로 다른 시즌의 3분의 1 수준이다. 짧은 시즌에서 고유율이 100%로 나오는 것은 부분적으로 길이 효과다. 130라운드짜리 시즌 2가 85.4%를 유지한 것과 같은 무게로 비교하면 안 된다.

남는 이야기

결론을 한 줄로 줄이면 이렇다. 유머 리그의 주제 재활용 문제는 실재했고, 지금은 거의 없다. 시즌 1의 고유율 21.1%에서 시즌 11 이후의 98~100%까지, 개선의 폭은 리그의 어떤 지표보다 크다.

다만 그 과정에서 확인된 사실 하나는 남겨 둘 만하다. 반복을 막는 장치는 자기가 볼 수 있는 형태의 반복만 막는다. 문자열 목록은 문자열을 막았고, 그러자 반복은 “갑작스러운 소나기”에서 “폭염 속 갑작스러운 소나기”로 모습을 바꿔 통과했다. 한글 토큰 추출이 붙기 전까지 “폭염”은 아홉 번 통과했다. 회피 목록이 정교해질수록 반복은 그 목록이 보지 않는 층위로 옮겨간다.

그래서 이 집계는 계속 다시 해 볼 만하다. 지금 시즌 15·17이 100% 고유라는 것은 이번 감사가 성공했다는 뜻이지, 다음 층위의 반복이 없다는 뜻은 아니다. 예컨대 소재는 전부 다르지만 구도가 매번 “39도 폭염 속 ○○의 그 1초”인 시즌이 있다면, 문자열 대조로는 100% 고유하게 보인다. 실제로 시즌 13에는 “~그 순간/~그 1초” 형태의 주제가 여럿 있었다. 다음 감사의 대상은 아마 그쪽일 것이다.

읽는 쪽에서 쓸 수 있는 결론은 단순하다. 초기 시즌 리포트를 볼 때 같은 주제가 계속 나오는 것은 착시가 아니다. 시즌 1 리포트의 90행짜리 표에서 “택배를 기다리는 마음”을 세 보면 열다섯 번이 나온다. 그리고 시즌 17 리포트에서는 같은 주제가 두 번 나오는 일이 없다.

집계 기준. 칼라톤 유머 리그 공개 시즌 리포트 10편(시즌 1·2·3·5·7·9·11·13·15·17)의 ‘전체 라운드 우승 코멘트’ 표 647행에서 라운드 번호·주제·우승 모델·점수를 파싱했다. ‘주제 문자열’은 표기가 완전히 같은 것끼리, ‘소재군’은 문자 2연쇄(bigram) 자카드 유사도 0.45 이상인 문자열을 연결 성분으로 묶어 셌다. ‘재출연 간격’은 같은 시즌 안에서 연속한 두 등장의 라운드 번호 차이다. 점수 평균에서는 시즌 1의 0점 기록 8건을 제외했고, 라운드 수 집계에는 포함했다. 국·영문 대조는 각 시즌 -en 리포트의 같은 표를 같은 방식으로 집계해 비교했다. 시즌마다 심사위원 수와 채점 기준이 달라 시즌 간 점수의 직접 비교는 피했고, 반복 대 단발 점수 비교는 소재군 기준으로 묶은 뒤 시즌 안에서만 했다. 인용한 코드는 저장소의 Humor/PlayBackend/models/HumorSeason.js·NewsCollector.js 현재 내용이며 각 시즌 진행 시점의 배포본과 동일하다고 단정하지 않았다.