Postmortem · 2026-05-31

QC 자동화 포스트모템
— 비싸게 배운 싼 정답

구독자는 아직 25명, 운영자는 혼자, 게다가 저는 일본어가 N5~N4 수준이라 제가 만든 콘텐츠를 직접 검수하지도 못합니다. 맡길 사람도, 고용할 돈도 없었습니다. 하지만 틀린 해설 한 줄은 그대로 사용자에게 전달됩니다. 그래서 퀴즈 7,500문항·단어 15,000개를 사람 없이 검수하는 길을 팠고 — 이건 fine-tuning과 LLM 판사에 돈을 쏟은 끝에 "구조는 공짜 린터, 의미는 코딩 에이전트"라는 싼 정답에 도달한 기록입니다. 그리고 그 길에서 "크레딧이 남아 있으니 괜찮겠지"가 ₩87만 청구로 돌아온 이야기이기도 합니다.

CONTENT퀴즈 7,500+ · 단어 15,000+
SUBSCRIBERS25명
ENGINE COST NOW$0 / 무료 린터

00왜 만들었나

솔직히 말하면, 저 자신이 일본어가 N5~N4 수준입니다. 정작 제가 만든 콘텐츠의 해설이 맞는지, 문장이 자연스러운지 스스로 검증할 수가 없습니다. 그렇다고 검수를 맡길 사람을 고용할 여력도, 도와줄 사람도 없었습니다. 개인이 혼자 운영하는 앱이니까요.

그러니 선택지가 없었습니다 — 사람이 못 하면 기계가 해야 했습니다. 목표는 단순했습니다: 퀴즈 7,500문항·단어 15,000개를 사람 손 거의 없이 내부 품질 기준 4.5점 이상으로. 문제는 "어떻게"였고, 일본어를 모르는 제가 처음 잡은 답이 "그럼 똑똑한 AI한테 다 맡기자" — fine-tuning + LLM 판사였습니다. 결과적으로 그게 비싼 길이었습니다.

TL;DR

01일자별 타임라인

아래 날짜는 git 커밋·CHANGELOG·학습 로그 기준 실측입니다. (전부 2026년 5월에 일어난 일 — 이 작업은 그 이전에 시작하지 않았습니다.)

2025-10 ~ 2026-04

맨손 검수 시절

admin에 Gemini/GPT "단건 AI 검수" 버튼을 붙여 손으로 한 문항씩 돌리던 단계(2025-10). 2026-04-26~30에 검수 페이지(단일 문항 모드·백업/undo·품질 점수)를 정비. 아직 자동화는 아님.

2026-05-22

QC 자동 파이프라인 착수

광역 스캔 + 정적 린터 + sonnet judge 도입(Plan A). "AI한테 검수를 맡긴다"가 본격 시작된 날.

2026-05-23

ft v1 · v2 학습

Vertex AI Gemini 2.5 Flash 파인튜닝 시작. v1 712건(jobId 765240009665019904), v2 1,244+139건(jobId 4038002340437950464). "전용 모델이면 싸게 검수되겠지"라는 가정.

2026-05-25

품질 자동화 + 일일 검수 cron

콘텐츠 품질 린터 + 매일 04:00 무인 린트. 단어 9,348→15,310개 확장. 여기 이미 "공짜 린터($0)"의 씨앗이 있었는데, 정작 더 비싼 쪽으로 달리는 중이었다.

2026-05-26

복수정답 대입 검증 엔진 + 피드백 자동 폴리싱

빈칸에 각 보기를 AI로 대입해 복수정답을 찾는 멀티모델 cascade. 피드백 30분 배치 파이프라인.

2026-05-27

ft v3 학습+배포 (정점)

1,865건 학습(endpoint 3309908781361528832). 복수정답 749→1건(99.9%). 전수 sweep. CHANGELOG에 "ft v3 학습 ~$5"로 기록 — 이 추정이 한참 빗나갔다는 건 며칠 뒤 결제 메일로 알게 된다.

2026-05-28 ~ 29

Snowball QC 엔진 대폭발

이름부터 거창했습니다 — "검수→수정→검토, 돌릴수록 비용↓·품질↑·엔진강화"라는 스노우볼 서사. 무인 데몬이 2시간마다 샘플을 뽑고, confident learning·weak-supervision·자동 revert·RAG까지. 5/29 하루에만 QC 커밋 69건. 밤새 데몬을 굴리며 "이게 굴러간다"고 뿌듯해하던 그때, sonnet 판사 호출이 매일 조용히 새고 있었습니다.

2026-05-30

대전환

"구조는 엔진이, 자연스러움 판단은 코딩 에이전트(Codex)를 믿어보자" 한마디에서 시작. 엔진=탐지 전용($0), ft/sonnet 봉인, Codex 협업 하네스(Issue→PR→린터 게이트), 데이터 git 추적, 데몬 누수 차단, ft 엔드포인트 전부 undeploy.

2026-05-31

지금 — 에이전트 2개로 검수

Codex가 고치고 Claude가 검수(머지/반려)하는 흐름으로 운영. 같은 날, GCP ₩500,000 결제 메일을 받고 Google Cloud Support 케이스를 열었습니다(아래 02장). 비싼 길을 한 바퀴 다 돌고 나서야 싼 정답이 보였습니다.

02크레딧 착시 — ₩87만의 교훈

이 글을 공개하는 가장 큰 이유입니다. 다른 분들은 같은 실수를 안 하시도록.

Google Cloud Billing 화면에 GenAI App Builder Trial Credit 잔액이 남아 있었습니다. 이름이 "GenAI"라서, 저는 이 크레딧이 Vertex AI 파인튜닝이나 Gemini 비용에도 당연히 적용될 거라 생각했습니다. 그 믿음으로 일본어 데이터 검수를 위해 Gemini 2.5 Flash tuning을 마음껏 돌렸습니다.

며칠 뒤 "₩500,000 결제 적용" 메일이 왔습니다. Billing을 열어보니 2026-05-01~26 사이에 약 ₩874,192가 발생해 있었고, 그중 ₩500,000이 이미 청구된 상태였습니다. 내역은:

크레딧은 한 푼도 적용되지 않았습니다. Google Cloud Support(상담사 Vivian)의 최종 확인:

지원팀 최종 답변

GenAI App Builder Trial Credit은 "Vertex AI Search" 전용 크레딧이며, Vertex AI · Gemini API · Gemini 2.5 Flash tuning SKU에는 적용되지 않습니다. Billing 화면에 크레딧 잔액이 보여도, 그게 모든 Google Cloud AI 서비스에 자동 적용된다는 뜻은 아닙니다.

심지어 상담 도중 지원 답변끼리 서로 충돌하기도 했습니다 — 한 답변은 "tuning에 적용 안 됨", 다른 답변은 "서비스 제한 없이 적용되어야 함". 결국 사람 상담사에게 다시 연결돼 "Search 전용"으로 정리됐습니다. 이 혼선 때문에, Vivian은 일반적인 dispute는 어렵지만 one-time service adjustment를 내부팀에 요청하겠다고 했습니다(케이스 #71690027). 확정된 환불이 아니라 검토 단계이며, 조정 금액이 전체보다 적을 수 있고 남은 잔액은 제 책임이라고 안내받았습니다.

튜닝 이후 비용에 대한 안내도 정리해 둡니다(같은 함정을 피하시도록):

튜닝 돌리기 전 체크리스트

03비용 회고 (대시보드 실측)

출처용도실측
Google Vertex AIGemini 2.5 Flash 파인튜닝/추론2026-05-01~26 ₩874,192 (tuning ₩787,525 + prediction ₩86,667). ₩500,000 청구됨. 크레딧 미적용.
Anthropicsonnet judge (QC 엔진)이번 달 약 $313 (~₩430k). 자동 충전이 켜져 있어 조용히 누적됨.
OpenAI멀티모델 cascade + 서버 gpt-4o-mini5월 인보이스 합 약 $225 (~₩310k). 이후 구독 전환으로 종량 차단.
합계 (2026-05)3사 합산(대략)약 ₩1.6M (~$1,200)
기록 vs 실제

CHANGELOG에 ft v3 학습을 "~$5"로 적어 뒀습니다. 엔진이 보고하는 LLM API 비용(복수정답 수정 ~$30, ft 학습 ~$5)만 보고 "싸게 했다"고 믿었던 거죠. 정작 큰 돈은 그 숫자가 닿지 않는 곳 — Vertex 튜닝 SKU(₩787,525)와, 안 쓰는데도 켜져 있던 엔드포인트 —에 있었습니다. "내 코드가 보고하는 비용"과 "결제 화면의 비용"은 다른 숫자입니다.

04자산 vs 낭비 (정직하게)

지출판정이유
sonnet judge 탐색 ($300대)자산결함 패턴 27종 + 린터 룰을 만듦 = 지금 공짜 엔진의 설계도. 지금도 PR 반려 근거로 쓰임.
ft v1·v2·v3 학습 (Vertex ₩87만)부분 자산복수정답 749→1 성과는 진짜. 단 재학습은 동결, 크레딧 착시로 비용은 예상보다 큼.
안 쓰는 엔드포인트 배포 유지낭비엔진이 ft를 더 안 쓰는데도 배포가 남아 있었음. 2026-05-30 전부 undeploy.
무인 데몬의 반복 sonnet 호출낭비자산화 안 되는 반복 소비. "켜두면 알아서"의 대가. 차단.

05지금의 구조

[탐지] 엔진 = 결정론 린터(무료, 외부 API 0) → 전수 린트 → "학습자 혼란" 구조 결함만 → GitHub Issue 자동 발행
[수정] Codex(코딩 에이전트, 정액 구독) → worktree 격리 작업 → 의미·자연스러움 수정 → PR
[검증] 별도 에이전트가 PR을 읽어 정답·복수정답·해설 동기화를 판정 + 구조 린터 회귀 게이트 → 머지/반려 → 배포

결과

퀴즈 1,336개 파일을 $0에 전수 린트해 구조 결함을 탐지하고, 의미 결함은 코딩 에이전트가 고치고 다른 에이전트가 검수합니다(추가 종량 $0, 정액 구독 한도 내). 실전 검증: 자동 린터 게이트가 코딩 에이전트의 실제 회귀(보기 한국어 중복)를 머지 전에 잡아냈고, 검수 에이전트가 정답 오류·복수정답·해설 desync가 든 수정 PR을 반려해 되돌렸습니다. 두 에이전트가 서로를 견제하는 것만으로 충분했습니다.

06전수 가능한 교훈

  1. 결정론 먼저, LLM 마지막. 검사 항목을 "기계 판정 가능 / 판단 필요"로 나눠라.
  2. 비싼 탐색의 산출물은 "규칙"이다. 모델이 찾은 패턴을 결정론 룰로 굳혀라. 안 굳히면 매번 돈 내고 재발견한다.
  3. fixer를 judge로 재심하지 마라. ground truth 없는 영역은 동급 모델 재심 = 핑퐁. 객관 게이트(린터 회귀)만 하드룰로, 의미는 "에이전트 2개 교차검증"으로 충분했다.
  4. "에이전트 2개면 됐을 걸"을 더 일찍 시험하라. 무인 LLM 자동화 엔진을 짓기 전에, 싸고 단순한 교차검증부터 돌려봤어야 했다.
  5. 클라우드 크레딧은 SKU 단위로 적용된다. "GenAI" 같은 이름만 보고 튜닝을 돌리지 마라. 잔액 표시 ≠ 내 작업에 적용.
  6. 배포된 모델 엔드포인트는 안 써도 호출이 남으면 청구된다. 안 쓰면 undeploy — 가장 흔한 클라우드 누수.
  7. "내 코드가 보고하는 비용"을 믿지 말고 결제 화면을 봐라. Budget alert는 알림일 뿐 자동 차단이 아니다.
  8. 무인 운영 비용을 매일 감사하라. "켜두면 알아서"가 가장 비싸다.

07논문을 실제로 엔진에 넣어본 경험

이 논문들은 인용만 한 게 아닙니다. 2026-05-29, "QC 엔진 v2"를 만들면서 직접 코드로 구현했습니다. 일본어를 검증 못 하니, 학계가 "정답 없이 데이터 오류를 찾는" 문제를 어떻게 푸는지 그대로 가져오려 했어요:

이걸 tools/qc-pipeline.mjs로 한데 묶고 docs/snowball-qc-v2.md 설계문서까지 썼습니다. 그런데 실제로 굴려보니 — 우리 데이터엔 과했습니다. 7,500문항은 ML 벤치마크처럼 거대하지도, 라벨이 마구 섞여 있지도 않았어요. 구조 오류는 결정론 린터가 확률 앙상블보다 싸고 확실하게 잡았고, 정작 의미 탐지에 쓴 LLM judge 앙상블이 바로 그 비싼 부분(데몬이 매일 새던 sonnet 호출)이었습니다.

그래서 결론은 역설적입니다 — "약한 신호를 결합한다"는 Snorkel의 문제 정의는 옳았지만, 그 풀 머신러닝 머신은 우리 규모엔 과했습니다. 우리에게 필요한 신호는 "확률 앙상블"이 아니라 "결정론 린터 1개 + 에이전트 판단 1개"로 충분했어요. 위 qc-* 서비스들은 지금도 코드에 남아 있되 운영 경로에선 빠졌습니다 — 탐색의 화석이자, "이론을 일단 끝까지 만들어봤기에 무엇이 과한지 알게 된" 증거입니다. 논문은 해답이 아니라 문제를 보는 틀을 줬습니다.

  1. Ratner et al. (2018). Snorkel: Rapid Training Data Creation with Weak Supervision. VLDB. arXiv:1711.10160
  2. Ratner et al. (2016). Data Programming: Creating Large Training Sets, Quickly. NeurIPS. arXiv:1605.07723
  3. Dawid & Skene (1979). Maximum Likelihood Estimation of Observer Error-Rates Using the EM Algorithm. JRSS-C.
  4. Northcutt et al. (2021). Confident Learning: Estimating Uncertainty in Dataset Labels. JAIR. arXiv:1911.00068
  5. Northcutt et al. (2021). Pervasive Label Errors in Test Sets Destabilize ML Benchmarks. NeurIPS. arXiv:2103.14749
  6. Zheng et al. (2023). Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena. NeurIPS. arXiv:2306.05685
  7. Liu et al. (2023). G-Eval: NLG Evaluation using GPT-4 with Better Human Alignment. EMNLP. arXiv:2303.16634
  8. A Survey on LLM-as-a-Judge (2024). arXiv:2411.15594

08한 줄 결론

비싸게 한 바퀴 돌아 싼 정답을 찾았습니다. 탐색비는 규칙으로 굳어 자산이 됐지만, "이거 그냥 린터로 되는 거 아냐?"와 "에이전트 둘이면 되는 거 아냐?"를 더 일찍 물었어야 했고, 안 쓰는 엔드포인트는 더 일찍 껐어야 했고, 크레딧은 이름이 아니라 SKU로 확인했어야 했습니다. 구독자 25명이라도, 그 25명이 보는 데이터의 품질은 타협하지 않습니다. 다만 이제는 그 품질을 LLM 종량제 반복 호출이 아니라, 결정론 린터와 검증 가능한 PR 흐름으로 지킵니다. 그리고 이 기록을 공개하는 이유는 하나 — 다른 분들은 이 학습비를 안 내셔도 되도록.