게임 채팅 로그는 운영 이슈를 가장 빨리 드러내는 신호 중 하나다.
문제는 모든 채팅을 사람이 계속 읽을 수 없고, 단순 키워드 필터만으로는 맥락을 판단하기 어렵다는 점이다.
결국 채팅 파이프라인에 LLM 분석을 붙여 운영 리포트를 만들었고, 이후 조정의 대부분은 운영자가 실제로 볼 만한 리포트만 남기도록 false positive를 줄이는 일이었다.
1. 배경
일반 채팅에는 운영에 도움이 되는 신호와 무시해도 되는 대화가 섞여 있다.
- 특정 스테이지나 보상에서 발생하는 버그 제보
- 핵, 매크로, 어뷰징 의심 정황
- 결제, 접속, 계정 관련 반복 이슈
- 단순 불만, 잡담, 농담, 밈, 개인 대화
처음부터 모든 메시지를 리포트로 만들면 운영자는 다시 노이즈를 사람이 걸러야 한다.
그래서 목표를 운영 액션으로 이어질 수 있는 신호 추출로 잡았다.
대화 전체를 요약하는 기능은 처음부터 배제했다.
2. 문제 정의
2.1 운영자가 원하는 결과물
운영자에게 필요한 정보를 다섯 가지로 좁혔다.
| 항목 | 설명 |
|---|---|
| 카테고리 | 버그, 핵/어뷰징, 결제/접속 이슈 등 |
| 제목 | 무엇을 확인해야 하는지 한 줄로 요약 |
| 근거 메시지 | 판단에 사용한 채팅 ID 또는 원문 일부 |
| 키워드 | 검색과 집계에 사용할 수 있는 짧은 단어 |
| 판단 이유 | 왜 운영 이슈로 봤는지 |
반대로 아래와 같은 내용은 리포트가 되면 안 됐다.
- "게임 어렵다", "운영 별로다" 같은 일반 불만
- 한두 문장만으로 판단하기 어려운 모호한 표현
- 유저 간 농담이나 밈
- 증거 메시지 없이 모델이 추측한 내용
2.2 LLM을 붙이면 바로 해결될까?
LLM은 맥락을 읽는 데 강하지만, 운영 시스템에 붙일 때는 다른 문제가 생긴다.
- 일반 불만을 버그로 과대 해석할 수 있다
- 핵/어뷰징처럼 민감한 카테고리를 근거 없이 만들 수 있다
- 긴 대화 윈도우에서 중요한 메시지와 잡담을 섞어 판단할 수 있다
- 모델 응답 포맷이 조금만 흔들려도 저장/조회 로직이 깨질 수 있다
결국 작업의 대부분은 모델 앞뒤에 있는 분석 단위, 프롬프트, 저장 기준, 테스트 더블을 정하는 일이었다.
3. 처리 흐름
채팅을 메시지 단위로 바로 분석하지 않고, 일정 범위의 윈도우로 묶어서 분석했다.
단일 메시지만 보면 농담인지 신고인지 구분하기 어렵고, 너무 긴 윈도우는 잡담이 섞여 판단이 흐려진다.
그래서 dev/prod 환경별로 윈도우 기준을 조정하면서 운영자가 확인할 수 있는 단위로 맞췄다.
윈도우 기준은 지금도 서비스 상황에 따라 조정 중이라, 특정 수치를 정답으로 적기는 어렵다.
4. 프롬프트 개선 방향
프롬프트에서 중요했던 것은 무엇을 문제로 보지 말아야 하는지를 명확히 하는 일이었다.
4.1 제외 기준을 먼저 정한다
리포트 대상에서 제외할 조건부터 프롬프트에 명시했다.
- 일반 잡담
- 근거 없는 추측
- 단순 밸런스 불만
- 운영자가 확인할 액션이 없는 대화
- 카테고리를 특정할 수 없는 대화
LLM은 친절하게 무언가를 만들어내려는 경향이 있다.
그래서 "애매하면 만들지 말라"는 기준을 강하게 주자 false positive가 줄어드는 경향이 있었다.
도입 전후의 리포트 건수나 none 비율을 계측해 둔 것은 아니라서, 여기서 효과는 제외 기준을 추가한 뒤 잡담성 리포트가 저장되는 빈도가 눈에 띄게 줄었다는 관찰이다.
4.2 none도 정상 결과로 다룬다
운영 시스템을 만들 때 흔한 실수는 문제가 없다는 결과를 예외처럼 다루는 것이다.
하지만 채팅 모니터링에서는 대부분의 윈도우가 문제 없는 대화다.
그래서 none 카테고리를 실패가 아니라 정상 분석 결과로 취급했다.
필요한 경우에는 none도 저장해 분석 이력과 모델 판단 흐름을 추적할 수 있게 했다.
4.3 근거 메시지를 요구한다
리포트에는 반드시 판단 근거가 있어야 한다.
"핵 의심 유저가 있습니다" 수준의 응답은 운영자가 확인할 방법이 없다.
"A 유저가 비정상 재화 획득을 언급했고, B 유저가 동일 현상을 확인했습니다"처럼 어떤 메시지에서 그렇게 판단했는지가 응답에 들어와야 한다.
운영자가 바로 확인할 수 있으려면 제목과 요약보다 근거 메시지 ID와 키워드가 더 중요했다.
5. 서버 쪽 가드레일
프롬프트만 믿으면 운영 기능으로 쓰기 어렵다.
모델 출력은 항상 흔들릴 수 있으므로 서버 쪽에서 한 번 더 정리했다.
5.1 응답 정규화
모델이 내려준 카테고리, 제목, 키워드, 근거 메시지를 그대로 저장하지 않고 정규화했다.
- 허용된 카테고리만 저장
- 빈 제목이나 과도하게 긴 제목 보정
- 키워드 개수와 길이 제한
- 존재하지 않는 메시지 ID 제거
- 리포트 저장 대상 여부를 별도 조건으로 판단
이 정규화는 모델 출력이 어떻게 오든 운영 데이터로 저장 가능한 형태를 보장하기 위한 단계다.
5.2 confidence 기준은 보조 정보로 다룬다
처음에는 confidence를 강한 필터로 쓰는 방식을 고려했다.
하지만 모델이 부여한 confidence가 실제 운영 정확도와 항상 맞지는 않았다.
그래서 confidence는 임시로 약화하고, 카테고리/근거/제외 기준 중심으로 저장 여부를 판단하는 방향으로 조정했다.
6. 테스트 전략
실제 LLM을 호출하는 테스트는 느리고 불안정하다.
테스트에서는 fake LLM으로 응답을 고정해 두고 서버 동작만 검증했다.
- 일반 대화는 리포트가 생성되지 않아야 한다
- 버그/핵/어뷰징 신호가 있으면 리포트가 생성되어야 한다
none카테고리도 정상 분석 결과로 처리되어야 한다- 잘못된 메시지 ID나 빈 필드는 정규화되어야 한다
- 같은 윈도우가 중복 저장되지 않아야 한다
테스트가 고정하는 것은 모델 응답이 흔들려도 유지되어야 하는 서버 쪽 계약이다.
마무리
돌아보면 LLM 호출부는 전체 작업에서 작은 부분이었다.
대부분의 시간은 운영자가 볼 만한 리포트가 되도록 노이즈를 줄이고, 애매한 결과를 저장하지 않게 하고, 테스트 가능한 경계를 만드는 데 들어갔다.
AI를 운영 시스템에 붙일 때는 "무엇을 찾아낼 것인가"보다 "무엇을 버릴 것인가"가 더 중요했다.