AI가 쓴 초안, 발행 전에 실제로 무엇을 걸러내는가 — Fact-check + Quality Gate 2단계 실측 공개
“AI로 하루에 글 100개씩 뽑아내면 금방 상위 노출되겠지?”
이렇게 생각하고 계신다면, 실제로 매일 AI로 글을 자동 발행해 본 입장에서 드리고 싶은 말은 하나입니다. 양보다 먼저 막아야 할 게 있다는 것. 이 블로그도 매일 자정 무렵 GitHub Actions가 초안을 하나씩 생성하지만, 그 초안이 그대로 사이트에 올라가는 일은 없습니다. 반드시 두 단계의 자동 검증을 통과해야 합니다.
오늘은 “AI 블로그는 이렇게 품질을 관리해야 한다”는 일반론 대신, 이 블로그가 실제로 돌리고 있는 두 스크립트(fact-check.mjs, quality-gate.mjs)가 정확히 무엇을 검사하는지, 그리고 최근 실제로 무엇을 걸러냈는지를 코드와 함께 공개합니다.
1단계: Fact-check — Gemini에게 자기 글을 의심하게 만들기
첫 번째 관문은 초안이 생성된 직후 실행되는 팩트체크 단계입니다. 핵심은 단순합니다. Gemini에게 “이 본문에서 검증되지 않았거나 사실이 아닐 가능성이 있는 주장을 찾아 웹 검색으로 확인해 달라”고 요청하고, googleSearch 툴(Grounding)을 함께 켜서 모델이 실시간 검색 결과를 근거로 답하도록 만듭니다.
const res = await client.models.generateContent({
model: MODEL,
contents: prompt,
config: { tools: [{ googleSearch: {} }] },
});
응답이 정확히 NO_ISSUES면 factChecked: true로 표시하고 다음 단계로 넘어갑니다. 조금이라도 의심스러운 부분이 있으면 CHECK_NEEDED와 함께 구체적인 근거를 로그로 남기고, 그 초안은 자동으로 발행되지 않습니다. 모델 자신이 학습 데이터만으로 판단하는 게 아니라 실시간 검색 근거를 갖고 판단하게 만드는 것이 이 단계의 핵심 설계입니다.
2단계: Quality Gate — 팩트체크 이후의 기계적 최종 점검
팩트체크가 “내용이 맞는가”를 본다면, 품질 게이트는 그 이후 발행 직전 마지막으로 아래 네 가지만 기계적으로 확인합니다.
| 검사 항목 | 기준 |
|---|---|
| 팩트체크 완료 여부 | draft: false인데 factChecked가 true가 아니면 반려 |
| 미확정 데이터 마커 잔존 | 본문에 실측 데이터를 채워야 한다는 운영자 확인 요청 표기가 남아 있으면 반려 |
| 본문 최소 분량 | 400자 미만이면 반려 |
| 슬러그 중복 | 같은 파일명(슬러그)이 이미 존재하면 반려 |
화려한 점수 체계나 다단계 필터링 파이프라인이 아니라, 발행 사고를 막기 위한 마지막 안전장치에 가깝습니다. 이 네 가지 중 하나라도 걸리면 npm run quality-gate는 종료 코드 1로 실패하고, GitHub Actions 워크플로우 전체가 중단되어 해당 글은 발행되지 않습니다.
실제로 이 게이트가 걸러낸 것들
이 블로그의 소개 페이지에는 이런 문장이 있습니다.
“사실관계가 의심되는 내용은 사람이 직접 확인하고 수정한 뒤에만 발행합니다 — 실제로 지금까지 발행된 글 중 20% 정도에서 이 과정을 통해 실질적인 오류를 수정했습니다.”
이게 이 블로그가 공개적으로 밝히고 있는 유일한 실측 수치입니다. “100개 중 32개만 통과했다” 같은 자극적인 숫자는 존재하지 않습니다 — 이 파이프라인은 하루 1건씩 초안을 생성하는 구조이지, 한 번에 100개를 대량으로 테스트한 적이 없기 때문입니다. 대신 실제로 있었던 사례 몇 가지를 그대로 공개합니다.
- 한 초안은 실제 발행된 것처럼 구체적인 수치를 나열했지만, 그 수치가 들어갈 자리에 “운영자가 실측 데이터를 채워야 한다”는 플레이스홀더가 그대로 남아 있었습니다. 품질 게이트가 이를 잡아내 발행을 막았고, 사람이 직접 확인해서 없는 데이터는 삭제하고 실제 공개 가능한 수치로 대체한 뒤에야 발행했습니다.
- 다른 초안은 어떤 API가 실제로는 지원하지 않는 기능(“도메인 화이트리스트 우선순위 지정”)을 지원한다고 서술했습니다. 팩트체크가 이를
CHECK_NEEDED로 표시했고, 실제 API 문서를 확인해 지원하지 않는 기능이라는 사실로 정정한 뒤 발행했습니다. - 비교적 사소하게는, 본문 중 “압취할”처럼 문맥에 맞지 않는 오탈자를 팩트체크 단계가 짚어낸 적도 있습니다.
세 사례 모두 공통점이 있습니다. 걸러진 초안이 폐기되지 않았다는 것. 반려는 끝이 아니라 시작입니다. 문제가 된 부분만 사람이 고쳐서 다시 발행 절차를 밟습니다.
왜 “통과율”이 아니라 “교정 방식”이 중요한가
AI 콘텐츠의 품질을 이야기할 때 흔히 몇 %가 통과했는지에 초점을 맞추기 쉽습니다. 하지만 실제로 운영해 보면 더 중요한 질문은 따로 있습니다. 걸러졌을 때 무엇을 하는가. 이 블로그의 원칙은 두 가지입니다.
- 없는 데이터를 지어내지 않는다. AI가 실측 데이터를 요구하는 자리에서 근거 없는 숫자를 채워 넣는 대신, 정말 없는 데이터라면 그 주장 자체를 빼거나 정성적인 설명으로 바꿉니다.
- 의심스러운 사실 주장은 발행 전에 반드시 사람이 원문을 대조한다. 팩트체크가
CHECK_NEEDED를 반환했다는 것 자체가 “AI가 확신하지 못한다”는 신호이므로, 이 신호를 무시하고 정적 문구만 보고 병합하지 않는 것이 원칙입니다.
구글이 AI 콘텐츠를 판단하는 기준도 결국 비슷합니다. 구글은 공식 가이드라인에서 콘텐츠가 AI로 만들어졌는지가 아니라 얼마나 유용하고 정확한지를 본다고 명시하고 있습니다. AI가 초안을 쓰는 것 자체는 문제가 아니라, 검증 없이 그대로 내보내는 과정이 문제라는 뜻입니다.
마치며
이 블로그의 자동화는 “AI가 다 알아서 쓰고 발행한다”는 이야기가 아닙니다. 정확히는 “AI가 초안을 쓰고, 또 다른 AI 호출이 그 초안을 의심하고, 마지막에 기계적인 규칙이 실수를 한 번 더 막는다”에 가깝습니다. 그리고 그 과정에서 걸러진 것들은 버려지지 않고, 사람이 실제로 열어서 무엇이 문제였는지 확인한 뒤에만 발행됩니다. 화려한 통과율 숫자보다, 이 순서를 지키는 것이 훨씬 더 중요합니다.