대회 · 2026
국립국어원 AI말평 글쓰기 채점 능력 평가 회고
최종 27/51위, 그리고 대회가 끝난 뒤에야 찾은 더 큰 문제
로컬 검증은 전부 통과했는데, 실제로 부족했던 건 숫자가 아니라 설명이었다.
국립국어원 언어정보나눔터가 주최하는 「인공지능(AI)의 한국어 능력 평가」
경진대회 2026년 과제 중 하나인 「글쓰기 채점 능력 평가」에 참가했다.
팀명은 소프트크리넥스였고, 51팀 중 27위로 마쳤다.
- 작업 시작: 2026년 7월 13일 (첫 베이스라인 Docker 후보 구현)
- 작업 종료: 2026년 8월 28일 (최종 리더보드 확인, git 이력 정리)
- 대회 공식 기간: 2026년 7월 1일 – 2026년 8월 25일(예선 마감)
- 공식 제출 시각: 2026년 8월 15일 14:03 KST (2차 제출, 최종 채택된 모델)
대회가 뭘 요구했나
입력은 한국어 논증적 글(에세이) 한 편과 그 글의 주제 프롬프트였다. 출력은 내용(content)·구성(organization)·표현(expression) 3영역의 1~5점 정수 점수와, 각 점수의 근거(rationale)였다. 제출물은 Docker 이미지 하나로, 안에서 OpenAI 호환 chat API 서버가 떠서 추론 요청을 받는 구조여야 했다. 외부 API 호출이나 비공개 모델은 금지였고, 단일 L40S 48GB GPU 한 장 안에서 전체 추론이 끝나야 했다.
평가는 RMSE 45% + Spearman 45% + LLM Judge 10%로 구성됐다. 즉 숫자를 맞히는 것(RMSE, Spearman)과 그 숫자를 설명하는 글이 실제로 타당한지 (LLM Judge)를 같이 봤다. 처음에는 "점수만 잘 맞히면 되지 않을까"라고 생각했는데, 끝나고 보니 이 가정이 가장 크게 틀렸다.
어떻게 시작했나
TF-IDF+Ridge로 돌리는 규칙 기반 rationale 생성기부터 시작해서, KoELECTRA 파인튜닝, 그리고 KLUE-RoBERTa-large까지 단계적으로 모델을 쌓았다. 6-fold OOF(out-of-fold) 검증을 기준으로 삼았는데, 그냥 평균 RMSE/Spearman이 좋아졌다고 승격하지 않고 행(row)·문항(prompt)·문항×수집계열(prompt×family) ·fold 4종류의 cluster bootstrap 신뢰구간이 전부 0을 포함하지 않아야 통과로 쳤다. 이 기준을 통과한 3모델 cross-fit 블렌드로 2026년 7월 20일 11:50 KST 1차 제출을 했다.
데이터를 4배로 늘린 2차 제출이 대성공
1차 제출 뒤 국립국어원 언어정보나눔터에서 승인받은 원자료(「글쓰기 채점 자료 말뭉치 2023/2024」, 11,981건)를 확보했다. 바로 쓰기 전에 먼저 "이게 대회 데이터와 같은 걸까?"를 코드로 검증했다. essay는 문단을 구분자 없이 이어붙이고, score는 두 평가자 총점의 평균을 항목 수로 나누는 공식으로 재구성했는데, 이 두 공식만으로 대회가 준 2,400행과 2,400/2,400 완전 일치가 나왔다. 그제서야 겹치지 않는 9,581행을 안심하고 추가 학습 데이터로 썼다.
klue_balanced 소스만 이 증강 데이터로 바꾸고 4모델을 다시 cross-fit한 후보를 2026년 8월 15일 14:03 KST에 2차로 제출했고, 같은 날 실제 결과를 확인했다.
| 1차(v5) | 2차(v6, 실제) | |
|---|---|---|
| 평가 점수 | 0.3790000 | 0.6050000 |
| 테스트 RMSE | 0.5217000 | 0.4714000 |
| 테스트 Spearman | 0.6214000 | 0.6727000 |
| LLM Judge | 3.0179000 | 3.0119000 |
로컬 OOF 개선이 리더보드에 그대로 재현됐다. 이게 최종까지 유지된 유일한 공식 제출이 됐다.
더 좋은 모델을 만들어 놓고도 제출하지 않았다
2차 제출 이후에도 작업은 계속했다. v7(organization 방어형 블렌드),
v8(4모델 전체를 증강 데이터로 재적합, 로컬 지표가 이번 세션 최고),
v9(분포 이동 대비 희석 블렌드)까지 전부 Docker 빌드, GHCR 공개 배포,
무인증 pull 검증까지 기술적으로는 완성했다. 특히 v8은 로컬 6-fold OOF
0.617871/0.547978로 v6(0.631221/0.528229)보다 두 지표 모두 좋았다.
그런데 제출하지 않았다. 39~51팀 규모의 리더보드에서 이 정도 개선이
중앙 순위를 top 5 안으로 끌어올릴 것 같지 않다는 판단 때문이었다.
결과적으로 이 판단은 맞았다. 끝나고 보니 1~5위와 우리의 RMSE·Spearman
격차는 크지 않았다(RMSE 0.43~0.46 vs 우리 0.4714, Spearman
0.72~0.77 vs 0.6727). 진짜 벌어진 지표는 LLM Judge였다(상위권
4.2~4.7, 우리 3.0119). 점수모델을 더 다듬는 것보다 근거(rationale)
품질을 올리는 게 순위에 더 크게 작용했을 가능성이 높다는 뜻이다.
마감 전 네 번 실험하고 네 번 다 정직하게 기각했다
마감이 다가오면서 v8을 더 개선할 수 있는 네 가지 아이디어를 시도했다. 이번에는 결과를 보고 기준을 정하지 않고, 실행 전에 통과 기준을 코드로 먼저 커밋한 뒤에만 실행하는 규칙을 지켰다.
- KoELECTRA 독립 seed로 재학습해 평균 내기 (seed bagging)
- 평가자 1·2 점수를 따로 예측하는 멀티태스크 헤드 (paired-rater)
- 문항×수집계열 12그룹에 대한 online GroupDRO
- organization이 유독 약한 행에 집중한 within-row 편차 보조 loss
넷 다 fold-0 사전등록 기준을 만족하지 못해 기각했다. 특히 4번은
organization 지표만 보면 분명히 좋아졌다(RMSE/Spearman
0.735272/0.557612 → 0.724137/0.569246). 하지만 expression이
나빠지면서 전체는 악화됐고(Spearman -0.002037), 사전에 정한 기준대로
승격하지 않았다. 매력적으로 보이는 부분 승리에 흔들리지 않을 수 있었던
건 순전히 "실행 전에 기준을 먼저 적어 놓는" 절차 덕분이었다.
LLM로 rationale을 고치려다 만난 벽
규칙 기반 rationale의 LLM Judge 점수가 가장 큰 약점이라는 걸 알고 Qwen3.5-4B/9B로 대체를 시도했다. 네 단계(자유 인용 → 72행 pilot → 선택형 quote → quote+category 선택 후 결정적 렌더러로 문장 조립)를 거쳐 마지막 버전에서는 90자 이내, 인용부호 균형, 중괄호 0 같은 형식 계약을 72개 전부 통과시켰다.
그런데 그 인용이 실제로 판단을 뒷받침하는지 72개를 손으로 전수 감사해 보니, 완전히 지지하는 경우는 43개뿐이었고 15개는 인용은 있지만 그 인용이 선택한 판단을 뒷받침하지 않았다. 형식은 완벽한데 의미는 아니었다. 결국 네 버전 모두 기각하고 끝까지 규칙 기반 rationale을 썼다. 자동화된 형식 검사만으로는 LLM 출력의 의미 품질을 보장할 수 없다는 걸 직접 겪은 셈이다.
대회가 끝난 뒤에 찾은 더 큰 문제
예선이 끝나고(8/25) 8/28에 최종 리더보드를 확인한 뒤, 이 프로젝트를
포트폴리오로 정리하면서 전체 git 이력을 다시 훑었다. 그러다
rationale_grounded_quote_pilot_* 실험 폴더에 있던 입력 파일 3개에
국립국어원 원자료의 실제 학생 에세이 원문이 그대로 커밋되어 있는
걸 발견했다. 대회 규정("원문 공개는 금지")과 우리가 직접 적어둔
원칙을 어긴 상태였다.
다행히 확인해 보니 이 커밋들은 GitHub의 origin에 한 번도 올라간
적이 없었다(로컬이 원격보다 150개 넘는 커밋 앞서 있었다). 그래서
git filter-repo로 전체 154개 커밋 이력에서 해당 파일 3개를 완전히
제거하고, 재발 방지용 .gitignore 규칙을 추가한 뒤에야 처음으로
GitHub에 push했다. 모델 성능 이슈가 아니라 데이터 취급 규율
이슈였다는 점에서, 가장 뒤늦게 찾았지만 가장 중요하게 다뤘어야 할
문제였다.
복기
- 숫자(RMSE/Spearman)는 상위권과 큰 차이가 없었다. 결정적으로 뒤처진 건 LLM Judge였다. 마감 막판의 GPU 자원을 점수모델 미세개선 대신 rationale 품질에 더 썼어야 했다.
- "검증을 전부 통과했다"와 "제출할 가치가 있다"는 다른 질문이다. v8을 끝내 제출하지 않은 판단은 사후적으로도 합리적이었다.
- 사전에 통과 기준을 적어 두는 습관이 없었다면, organization만 좋아진 실험을 잘못 승격했을 가능성이 크다.
- 데이터를 다루는 프로젝트에서는 "원문이 공개되면 안 된다"는 규칙을 코드 리뷰 체크리스트가 아니라 커밋 전 자동 검사로 만들어야 한다. 이번에는 운이 좋게 원격에 올라가기 전에 잡았을 뿐이다.
전체 과정과 실험별 알고리즘, 수치, 운영진 문의 기록은 저장소의
PORTFOLIO.md에 더 자세히 남겨 두었다.