유료 결과물 앞에 LLM QA 게이트 설치하기: fail-closed 검토, 단 한 번의 자가 치유, 재시도 루프 없음
요약
1인 AI 서비스 운영자가 유료 결과물의 품질을 보장하기 위해 LLM QA 게이트를 구축한 사례를 다룹니다. 실패 시 차단(fail-closed) 원칙과 자가 치유 메커니즘을 통해 자동화된 검토 프로세스를 설계하는 실무적인 엔지니어링 접근법을 설명합니다.
핵심 포인트
- 결과물 발송 전 LLM을 검토자로 활용하는 QA 하위 프로세스 구축
- 모델 오류나 타임아웃 시 결과물을 차단하는 fail-closed 원칙 적용
- 디스크 기반의 단계별 파이프라인 설계를 통한 디버깅 및 재개 용이성 확보
- LLM의 비정형 응답을 안정적으로 처리하기 위한 견고한 파싱 전략 필요
TAGS: ai, node, automation, playwright
나는 컴플라이언스 보고서(compliance-report) 서비스를 구축하고 출시했다. 도메인 등록, Stripe 결제 활성화, 풀필먼트(fulfillment) 자동화까지 달력 기준 일주일도 채 걸리지 않았다. 한 분기(quarter)가 아니다. 팀도 아니다. AI 네이티브 툴체인(toolchain)을 갖춘 단 한 명의 개인이다. 이 포스트의 핵심은 속도가 아니다. 그 속도를 가능하게 만든 구체적인 엔지니어링 요소에 관한 것이다. 왜냐하면 이는 대부분의 1인 빌드(solo builds)가 건너뛰었다가 나중에 큰 대가를 치르게 되는 부분이기 때문이다.
파이프라인은 쉬운 부분이다
이 제품은 공공 부문 웹사이트의 ADA Title II 접근성을 감사하고 증거 바인더(evidence binder)를 생성한다. 파이프라인은 의도적으로 지루하게 설계되었다. 각 단계가 디스크에 JSON을 기록하는 CLI 단계의 체인이다:
crawl-scan.mjs → N개 페이지에 대해 Playwright + axe-core 실행 → findings.json
pdf_census.py → 모든 연결된 PDF, 태그 지정/미지정 여부 → pdf-census.json
summarize.mjs → 심각도 가중치 점수(severity-weighted score) → summary.json
...
메모리 내 상태(in-memory state)가 아닌 디스크 상의 파일들이다. 모든 단계는 재개(resumable) 가능하고, 검사(inspectable) 가능하며, 단일 도시의 디렉토리를 대상으로 다시 실행(re-runnable)할 수 있다. 이것은 아키텍처의 순수성을 위한 것이 아니다. 밤 11시에 시청 웹사이트를 다시 크롤링하지 않고도 PDF의 9페이지를 디버깅할 수 있게 해주는 실용적인 방법이다.
이 중 어려운 것은 아무것도 없다. AI의 도움을 받아 그 체인은 빠르게 완성되었다.
당신이 고용할 수 없는 부분
1인 운영자가 돈을 받는 것을 실제로 가로막는 요소는 바로 이것이다: 결과물이 나가기 전에 아무도 작업을 확인하지 않는다. 회사에서는 이것이 하나의 역할(role)이다. 누군가 결과물을 읽고 스크린샷에 마커가 누락된 것을 발견하여 발송을 중단한다. 혼자라면 당신이 생성자(generator)이자 검토자(reviewer)가 되는데, 자동화된 파이프라인의 모든 산출물을 영원히 검토할 수는 없다.
그래서 검토자를 하위 프로세스(subprocess)로 만들었다. 어떤 바인더가 이메일로 발송되기 전에, 헤드리스 모델(headless model)이 실제 PDF와 스캔 데이터, 그리고 비전(vision) 기능을 통해 증거 스크린샷을 읽는다:
const prompt = `당신은 유료(PAID) 결과물을 검토하는 인도 전 QA 검토자입니다.
읽기: readiness-binder.pdf (모든 페이지), summary.json, evidence/*.png (직접 보세요).
엄격하게 확인하십시오:
...
그 안에는 세 가지 핵심적인 요소가 있으며, 저는 처음에 이들 모두를 잘못 다루었습니다.
검토자 자체에 대해서도 fail-closed(실패 시 차단)를 적용합니다. 모델이 타임아웃되거나, 충돌하거나, 쓰레기 값을 반환하면 판정은 pass: false가 됩니다. 고장 난 심판이 결코 통과(green light) 신호가 되어서는 안 됩니다. 모든 실패 경로는 판정 결과와 함께 사람의 편지함으로 전달되도록 경로를 설정합니다.
관대하게 파싱(Parse)하지 않으면 제대로 된 작업물도 오판하여 실패 처리하게 됩니다. "JSON만 출력하세요"라는 말은 일종의 제안일 뿐입니다. 코드 펜스(Code fences), 길을 잃은 문장 하나, 산문 속의 외로운 { 하나 때문에 — 초기에는 완벽하게 괜찮은 바인더(binders)들이 포맷팅의 특이점 때문에 차단되었습니다. 해결책은 문자열을 훑으며 코드 펜스와 서문을 무시하고, 파싱이 가능하며 pass 키를 포함하는 첫 번째 균형 잡힌 {...}를 찾는 스캐너를 사용하는 것입니다. 결과물에는 엄격하되, 봉투(포맷)에는 관대해야 합니다.
자가 치유(Self-heal)는 결과물이 아닌 생성기를 수정하며, 정확히 단 한 번만 수행합니다. 게이트가 거부하면, 헤드리스 코딩 세션(headless coding session)이 발견된 문제점과 리포지토리(repo) 접근 권한을 부여받아 실행됩니다. 이때 엄격한 규칙이 적용됩니다: 오직 src/만 수정할 것, 생성된 PDF를 수동으로 패치하지 말 것, 이메일이나 결제 로직은 절대 건드리지 말 것, 그리고 수정 사항을 커밋할 것. 그 후 결과물이 다시 생성되고 게이트가 재검토를 수행합니다. 단 한 번의 시도만 허용합니다. 핵심 경로(money path)에서 재시도 루프(retry loop)를 만드는 것은 고장 난 것을 배포하는 속도를 늦출 뿐입니다.
무엇을 잡아냈는가
이 게이트는 도입 초기 며칠 만에 제 값을 했습니다. evidence.mjs가 번호가 매겨진 플래그를 마지막 스크롤 이전에 배치하고 있어서, 배지가 캡처된 프레임 밖에 위치하게 되었고 가시적인 번호 매기기가 #2부터 시작되었습니다. JSON 매니페스트(manifest)에는 주석이 4개라고 되어 있고 실제로 4개의 주석이 존재했기 때문에, 제가 직접 했다면 그대로 배포했을 결함이었습니다. 오직 PNG를 직접 보는 것만이 이를 잡아낼 수 있습니다. 해결책은 해당 결함이 발견된 날짜를 명시한 주석과 함께 생성기에 반영되었습니다.
이것이 진정한 속도에 대한 논거입니다. AI가 코드를 빠르게 작성한다는 것이 핵심이 아닙니다. 보통 인력 한 명과 일주일의 시간이 소요되는 검토 루프가 이제는 fulfillment 스크립트에서 호출할 수 있는 하위 프로세스(subprocess)가 되었다는 점입니다. 따라서 아이디어가 실제로 배포되어 결제를 받기까지 며칠밖에 걸리지 않으며, 사용자가 지켜보지 않을 때도 신뢰성을 유지할 수 있게 됩니다.
그것이 바로 우리가 CivicBinder를 구축한 방식입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기