문제는 정답보다 주변 단어에서 먼저 보였습니다
정답 후보를 고르는 일은 처음에는 단어 자체를 보는 문제처럼 보였습니다. 길이가 적당한지, 민감어가 아닌지, 품사가 맞는지 정도를 통과하면 정답으로 쓸 수 있을 것 같았습니다. 실제 답안지를 만들어 보니 더 큰 문제는 정답 주변에 있었습니다.
어떤 단어는 정답으로는 그럴듯해 보여도 상위 유사도 단어들이 이상했습니다. 한 글자 단어가 많이 끼거나, 특정 분야의 드문 말이 가까운 쪽을 차지하거나, 사람이 봤을 때 다음 추측으로 이어가기 어려운 후보가 몰렸습니다.
이 경우 정답 단어만 보고는 문제를 잡을 수 없습니다. 플레이어는 정답을 직접 보지 않고 주변 단어와 점수만 봅니다. 그래서 정답 후보를 판단할 때는 그 정답의 가까운 이웃과 힌트 후보까지 같이 봐야 했습니다.
수동 blocklist만으로는 부족했습니다
초기에는 문제가 되는 단어를 발견하면 blocklist에 넣는 방식이 가장 빠르게 보였습니다. 실제로 `answer-blocklist.json`은 이런 단어들을 답안지에서 제외하는 용도로 쓰입니다. 유효한 단어지만 정답으로 내기에는 맞히기 어렵거나 플레이 흐름을 해칠 가능성이 있는 단어를 빼는 장치입니다.
하지만 blocklist만 늘리는 방식은 한계가 있습니다. 특정 단어 하나는 막을 수 있어도, 비슷한 유형이 계속 나오면 매번 사람이 찾아야 합니다. 또 어떤 단어는 정답으로는 제외해야 하지만 힌트로는 쓸 수 있습니다. 그래서 blocklist는 정답 전용으로 두고, 힌트 필터와 분리했습니다.
이 분리가 중요했습니다. 정답 후보를 줄이는 기준을 힌트에도 그대로 적용하면 가까운 힌트 묶음이 부족해집니다. 반대로 힌트 기준을 정답에 그대로 적용하면 정답으로 어색한 단어가 남습니다. 같은 어휘를 보더라도 정답과 힌트의 책임이 다릅니다.
가까운 힌트가 부족하면 정답을 바꿨습니다
정답 후보가 최종 답안지에 들어가려면 가까운 힌트 구간을 통과해야 합니다. 특히 20-30위, 30-40위, 40-50위, 50-70위, 70-100위처럼 정답에 가까운 구간을 봅니다. 이 구간은 플레이가 막혔을 때 실제로 중요한 힌트가 나오는 위치입니다.
한 후보가 여러 가까운 구간에서 충분한 샘플을 만들지 못하면 그 후보는 탈락합니다. 현재 빌드는 기본 450개 후보를 먼저 뽑고, 그중 300개를 최종 정답으로 채웁니다. 중간 후보가 실패하면 다음 후보가 들어옵니다.
이 방식으로 `insufficientCloseHints` 같은 실패를 빌드 단계에서 처리할 수 있게 됐습니다. 예전에는 문제를 만들고 나서 사람이 이상함을 발견해야 했지만, 지금은 답안지 생성 과정에서 부족한 후보를 자동으로 밀어냅니다.
상위 유사도 목록이 오염된 경우도 따로 봤습니다
가까운 힌트 개수만 충분하다고 끝나지 않았습니다. 샘플 개수는 채워졌지만 그 안이 희귀어, 전문어, 한 글자 단어, 부적절한 표면형으로 채워지는 경우가 있었습니다. 플레이어 입장에서는 힌트가 나왔는데도 방향을 잡기 어려운 상태입니다.
그래서 top-K 품질 검사도 추가했습니다. 상위 30개나 100개 안에 한 글자 단어가 많이 들어가면 `noisyTopK`로 보고, 가까운 구간이 희귀어 쪽으로 치우치면 `pollutedCloseHints` 같은 이유로 후보를 제외합니다. 정답과 직접 관련 없는 긴 희귀어가 top 1을 차지하는 경우도 따로 잡습니다.
이 검사는 수학적으로 완벽한 판정이 아닙니다. 대신 운영에서 실제로 문제를 일으킨 패턴을 막는 장치입니다. 단어 게임에서는 모델 점수보다 플레이어가 다음 단어를 생각할 수 있는지가 더 중요한 순간이 있습니다.
교체 작업에도 같은 기준을 적용했습니다
답안지를 한 번 만들었다고 끝나는 것도 아니었습니다. 이미 만든 주간 릴리스에서 정답 하나만 바꿔야 할 때가 있습니다. 이때 새 정답만 넣고 끝내면, 그 정답의 top-K, 일반 힌트, 히든 힌트가 기존 정책과 어긋날 수 있습니다.
그래서 교체 스크립트도 같은 필터와 힌트 정책을 쓰도록 고쳤습니다. 정답 하나를 바꾸면 `answers.json`, `answer-topk.json`, `answer-hints.json`, 필요한 경우 히든 힌트까지 같이 맞춰야 합니다. 한 파일만 바꾸는 방식은 안전하지 않았습니다.
결과적으로 필터는 단순한 전처리 코드가 아니라 운영 도구가 됐습니다. 좋은 정답을 고르는 일, 힌트를 고르는 일, 릴리스 중간에 정답을 바꾸는 일이 모두 같은 기준을 공유해야 주간 답안지의 품질이 유지됩니다.
지금도 판단 기준은 계속 남습니다
자동 필터가 늘어났다고 해서 사람이 볼 일이 사라진 것은 아닙니다. 한국어 단어는 품사 분석과 빈도만으로 판단하기 어려운 경우가 많습니다. 어떤 단어는 사전에는 있지만 일상 추측으로는 거의 나오지 않고, 어떤 단어는 드물어 보여도 게임에서는 좋은 실마리가 될 수 있습니다.
그래서 현재 구조는 모든 문제를 자동으로 해결한다기보다, 사람이 매번 직접 확인해야 하는 양을 줄이는 데 가깝습니다. 명백히 나쁜 패턴은 빌드에서 제거하고, 애매한 후보는 리포트와 테스트로 확인할 수 있게 합니다.
카맨틀에서 필터를 만들며 배운 점은 명확했습니다. 유사도 모델은 후보를 찾는 데 필요하지만, 게임의 재미를 보장하지는 않습니다. 정답과 힌트 필터는 모델의 결과를 사람이 플레이할 수 있는 문제로 바꾸는 마지막 단계입니다.