<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>AI Engineering on jyukki's Blog</title><link>https://jyukki.com/categories/ai-engineering/</link><description>Recent content in AI Engineering on jyukki's Blog</description><generator>Hugo -- 0.147.0</generator><language>ko-KR</language><lastBuildDate>Fri, 04 Sep 2026 10:06:00 +0900</lastBuildDate><atom:link href="https://jyukki.com/categories/ai-engineering/index.xml" rel="self" type="application/rss+xml"/><item><title>2026 개발 트렌드: LLM 평가는 점수표가 아니라 배포 결정을 위한 Guardrail이 된다</title><link>https://jyukki.com/posts/2026-09-04-llm-evaluation-decision-guardrail-production-trend/</link><pubDate>Fri, 04 Sep 2026 10:06:00 +0900</pubDate><guid>https://jyukki.com/posts/2026-09-04-llm-evaluation-decision-guardrail-production-trend/</guid><description>최근 GitHub의 secret scanning LLM 평가 사례를 바탕으로, 평균 점수를 모델 비교에 쓰는 데서 멈추지 않고 제품 결정·안전 제약·운영 비용을 함께 판단하는 배포 gate를 설계합니다.</description><content:encoded><![CDATA[<p>LLM 기능의 첫 데모는 대체로 빠르다. 몇 개의 정제된 예시와 잘 다듬은 프롬프트만으로도 그럴듯한 결과가 나온다. 하지만 production에서 필요한 질문은 다르다. 실제 문맥은 빠지고, 입력은 모호하며, 과거 라벨에는 운영 편의 때문에 닫힌 티켓도 섞인다. 품질 평균이 올라도 고위험 오류가 한 건 늘면 출시할 수 없는 기능이 있다.</p>
<p>이 차이를 잘 보여주는 최근 사례가 GitHub의 secret scanning LLM 평가다. GitHub는 false positive를 줄이는 것을 주된 제품 효과로 보되, 실제 credential을 놓칠 수 있는 recall 저하를 안전 제약으로 분리했다. 이어 지연·비용·신뢰성·production 호환성을 별도 운영 guardrail로 두고, prompt·model·dataset·pipeline의 버전을 재현 가능하게 기록했다. 이 사례의 중요한 점은 특정 모델의 우수함이 아니라 <strong>평가 결과를 배포 찬반의 증거로 바꾸는 구조</strong>에 있다.</p>
<p>이 글은 <a href="/posts/2026-04-20-synthetic-replay-eval-gate-trend/">Synthetic Replay 기반 평가 Gate</a>, <a href="/posts/2026-05-02-speculative-execution-verifier-loop-trend/">Speculative Execution과 Verifier Loop</a>, <a href="/posts/2026-07-07-agent-quality-flywheel-eval-runtime-trend/">Agent Quality Flywheel과 Runtime Eval</a>의 다음 단계다. 앞선 글이 재현과 검증 루프의 필요성을 다뤘다면, 여기서는 팀이 매 release에서 “이번 변경을 실제로 전진시켜도 되는가”를 결정하는 운영 기준을 만든다.</p>
<p>참고한 자료:</p>
<ul>
<li><a href="https://github.blog/ai-and-ml/llms/how-to-evaluate-llms-before-production/">GitHub Blog: How to evaluate LLMs before production</a></li>
<li><a href="https://github.blog/ai-and-ml/github-copilot/how-we-make-ai-coding-more-cost-efficient-without-sacrificing-task-quality/">GitHub Blog: How we make AI coding more cost efficient without sacrificing task quality</a></li>
</ul>
<h2 id="이-글에서-얻는-것">이 글에서 얻는 것</h2>
<ul>
<li>LLM 평가를 모델 ranking이 아니라 제품 의사결정으로 시작하는 방법을 배웁니다.</li>
<li>primary outcome, safety constraint, operational guardrail을 분리해 trade-off를 숨기지 않는 기준을 얻습니다.</li>
<li>prompt·model·context·pipeline 변경을 재현 가능한 release gate로 운영하는 방법을 정리합니다.</li>
<li>LLM-as-a-judge와 사람 검토를 비용 절감 장치가 아닌 위험 기반 triage로 배치할 수 있습니다.</li>
</ul>
<h2 id="핵심-개념이슈">핵심 개념/이슈</h2>
<h3 id="1-평균-점수는-배포-승인이-아니다">1) 평균 점수는 배포 승인이 아니다</h3>
<p>평가 지표가 0.82에서 0.86으로 올랐다는 사실은 출발점이지 결론이 아니다. 먼저 이 기능이 만들 제품 결정을 한 문장으로 고정해야 한다. 예를 들어 코드 리뷰 보조 기능이라면 “사람이 검토할 우선순위를 더 잘 정하는가”, 보안 분류 기능이라면 “불필요한 알림을 줄이되 실제 위험을 억제하지 않는가”가 질문이 된다. 질문이 없으면 정확도, 만족도, 비용처럼 성격이 다른 수치를 임의의 가중 평균으로 섞게 된다.</p>
<p>권장하는 구조는 세 층이다.</p>
<ul>
<li><strong>Primary outcome</strong>: 사용자가 얻는 직접 효과. 예: false-positive 감소, 검토 시간 감소, 유효한 제안 채택률.</li>
<li><strong>Safety constraint</strong>: primary outcome이 좋아도 넘으면 안 되는 손실. 예: secret 누락, 정책 위반 제안, 고위험 작업의 잘못된 자동 실행.</li>
<li><strong>Operational guardrail</strong>: 실제 제공 가능한지 판단하는 조건. 예: p95 지연, 요청당 비용, schema parsing 실패율, fallback 성공률.</li>
</ul>
<p>이 셋을 분리하면 precision이 크게 올랐지만 recall이 기준 아래로 떨어진 실험을 “승리”로 잘못 판정하지 않는다. GitHub의 사례도 false positive 감소를 목표로 두면서 recall을 안전 제약으로 취급했다. 즉 3%p의 사용자 편의 개선이 0.2%p의 치명적 누락 증가와 자동으로 교환될 수는 없다.</p>
<h3 id="2-offline-평가는-production-pipeline의-통합-테스트여야-한다">2) offline 평가는 production pipeline의 통합 테스트여야 한다</h3>
<p>clean benchmark는 모델 능력을 가늠하는 데 유용하지만, 실제 입력의 어려움을 보존하지 못한다. production에서는 후보 값 옆에 더 그럴듯한 값이 있고, 문맥이 잘리고, tool이 반환한 형식이 바뀌고, policy가 애매한 사례가 섞인다. 모델만 단일 문자열로 평가하면 실제 시스템과 다른 문제를 푸는 셈이다.</p>
<p>따라서 평가 fixture는 <code>입력 원문</code>, <code>retrieved context</code>, <code>tool output</code>, <code>system policy</code>, <code>parser/validator 결과</code>까지 포함한 pipeline snapshot으로 관리해야 한다. 민감 데이터가 있다면 <a href="/learning/deep-dive/deep-dive-test-data-contract-masking-synthetic-seed-playbook/">테스트 데이터 계약·마스킹·Synthetic Seed</a>처럼 최소 권한 원칙으로 가명·합성 데이터로 변환하되, 모호함과 실패 양상까지 지워서는 안 된다.</p>
<p>대표성은 샘플 수 하나로 끝나지 않는다. 다음처럼 slice를 분리해 보고하는 편이 실용적이다.</p>
<ul>
<li>정상 입력과 불완전·모순 문맥</li>
<li>일반 사례와 과거 incident·고액 거래·권한 변경 같은 high-impact 사례</li>
<li>충분한 context와 검색 실패·오래된 문서 context</li>
<li>새 형식과 legacy 형식, 한국어·영어 등 실제 지원 입력</li>
</ul>
<p>전체 평균이 통과해도 high-impact slice가 기준을 못 지키면 출시하지 않는다. 이것은 통계를 과도하게 복잡하게 만드는 일이 아니라, 실패 비용이 다른 사례를 같은 오류 한 건으로 세지 않기 위한 최소 장치다.</p>
<h3 id="3-변경-하나와-baseline-하나를-대응시켜야-원인을-안다">3) 변경 하나와 baseline 하나를 대응시켜야 원인을 안다</h3>
<p>LLM 시스템은 model뿐 아니라 prompt, retrieval, tool schema, 후처리, safety policy가 동시에 바뀐다. 이들을 한 번에 바꾸고 결과가 좋아지면 어느 변화가 효과를 냈는지, 다음 release에서 어느 부분을 rollback해야 하는지 알 수 없다.</p>
<p>각 평가 run에는 최소한 <code>run_id</code>, prompt version, model ID와 provider 설정, dataset version, context builder commit, parser/policy version, 실행 시간·비용을 저장한다. 그 다음 prompt-only, model-only, retrieval-only처럼 주요 변화 한 가지를 baseline과 비교한다. 두 변경을 결합한 결과가 필요하면 각각의 단독 결과를 남긴 뒤 마지막에 조합 실험을 한다.</p>
<p>초기 gate의 예시는 다음과 같이 쓸 수 있다. 이 숫자는 보편적 정답이 아니라 팀이 명시적으로 조정해야 할 출발점이다.</p>
<ol>
<li>primary outcome은 baseline 대비 통계적으로 의미 있는 개선 또는 최소 5% 상대 개선을 요구한다.</li>
<li>safety metric은 high-impact slice를 포함해 baseline보다 1%p 이상 후퇴하면 차단한다.</li>
<li>p95 지연이 SLO의 80%를 넘거나 요청당 비용이 예산의 90%를 넘으면 quality가 좋아도 canary까지만 허용한다.</li>
<li>총 평가 표본이 300건보다 작거나 high-impact 사례가 30건 미만이면 hard rollout 대신 더 작은 canary와 사람 review를 의무화한다.</li>
</ol>
<p>숫자보다 중요한 것은 release 전부터 “무엇이 통과이고 무엇이 보류인가”를 합의하는 일이다. 평가 후에 임계치를 고치면 지표는 의사결정 도구가 아니라 결과를 정당화하는 장식이 된다.</p>
<h2 id="실무-적용">실무 적용</h2>
<h3 id="1-위험도별로-평가와-rollout의-깊이를-다르게-한다">1) 위험도별로 평가와 rollout의 깊이를 다르게 한다</h3>
<p>모든 LLM 기능에 거대한 evaluation lab을 만들 필요는 없다. 대신 되돌리기 어려움과 영향 범위를 기준으로 경로를 나눈다.</p>
<table>
  <thead>
      <tr>
          <th>위험 등급</th>
          <th>예시</th>
          <th>offline gate</th>
          <th>online 단계</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>낮음</td>
          <td>문서 요약 초안</td>
          <td>형식·사실성 표본, 비용 상한</td>
          <td>opt-in 사용자 관찰</td>
      </tr>
      <tr>
          <td>중간</td>
          <td>코드 리뷰 우선순위</td>
          <td>slice별 품질·지연·acceptance 기준</td>
          <td>5% canary 후 확대</td>
      </tr>
      <tr>
          <td>높음</td>
          <td>secret 분류·권한 추천</td>
          <td>recall/정책 위반 hard gate, 사람 표본 검토</td>
          <td>shadow → 승인형 canary</td>
      </tr>
      <tr>
          <td>매우 높음</td>
          <td>결제·삭제·권한 변경 실행</td>
          <td>모델 점수와 무관하게 deterministic validation·사람 승인</td>
          <td>자동 실행 금지 또는 매우 제한적 승인형</td>
      </tr>
  </tbody>
</table>
<p>특히 high-risk 작업은 “모델이 99% 맞았다”는 평가를 실행 권한으로 바꾸지 않는다. 구조화된 입력 검증, policy engine, idempotency, 감사 로그처럼 모델 밖의 제어가 최종 결정자여야 한다. 이는 <a href="/posts/2026-07-15-ai-security-review-control-loop-trend/">AI Security Review Control Loop</a>에서 다룬 것처럼 AI 산출물 검토와 실행 권한을 분리하는 이유이기도 하다.</p>
<h3 id="2-llm-as-a-judge는-사람-검토를-없애지-않고-집중시킨다">2) LLM-as-a-judge는 사람 검토를 없애지 않고 집중시킨다</h3>
<p>judge 모델은 많은 표본을 빠르게 훑고, 평가 대상 모델과 라벨이 충돌하는 사례를 표시하는 데 유용하다. 하지만 judge도 같은 문맥 누락, policy 해석 차이, 모델 상관관계 문제를 가질 수 있다. judge가 “통과”라고 해도 ground truth가 되는 것은 아니다.</p>
<p>안전한 triage는 다음 흐름을 따른다.</p>
<ol>
<li>low-risk이고 judge·규칙·기존 라벨이 일치하는 표본은 자동 처리한다.</li>
<li>confidence가 낮거나 judge와 evaluator가 충돌한 표본은 사람에게 보낸다.</li>
<li>금전·보안·권한처럼 영향이 큰 표본은 confidence와 무관하게 사람 검토 비율을 유지한다.</li>
<li>자동 통과 표본도 매 run에서 무작위 5~10%를 audit해 systematic error를 찾는다.</li>
<li>judge prompt와 model 역시 versioned component로 평가한다.</li>
</ol>
<p>이 구조에서 사람 검토의 산출물은 단순한 승인/거절이 아니다. 새 failure label, fixture, policy clarification으로 다시 dataset에 들어가야 다음 run의 대표성이 높아진다.</p>
<h3 id="3-offline-통과-다음에는-작고-되돌릴-수-있는-online-실험을-둔다">3) Offline 통과 다음에는 작고 되돌릴 수 있는 online 실험을 둔다</h3>
<p>offline 평가가 production과 닮을수록 좋지만 완전히 같을 수는 없다. 실제 traffic 분포, 사용자 행동, upstream 지연, 새 input format은 online에서만 드러난다. 따라서 rollout은 <code>shadow → 1~5% canary → 단계 확대</code>처럼 한 방향으로 작게 가고, 단계마다 최소 관찰 창을 둔다.</p>
<p>관찰 지표도 offline 지표와 이어져야 한다. 예를 들어 false positive 감소를 목표로 했다면 실제 developer override율, 후속 incident, 사람이 되돌린 비율을 함께 본다. 한 시간의 품질 개선을 이유로 일주일 뒤 발견되는 안전 실패를 무시해서는 안 된다. rollback 조건은 canary 전 ticket이나 config에 적고, target model과 prompt를 한 번에 이전 baseline으로 되돌릴 수 있게 준비한다.</p>
<h2 id="트레이드오프주의점">트레이드오프/주의점</h2>
<p>대표성 높은 dataset을 만들수록 라벨 비용과 개인정보 처리 부담이 커진다. 이 부담 때문에 synthetic data만 쓰면 드문 실패가 과소대표되고, production label만 쓰면 “사용자가 빨리 닫았다”와 “정말 false positive였다”를 혼동한다. 두 데이터 소스를 섞되, 라벨 출처·신뢰도·마지막 검토일을 메타데이터로 남기는 편이 낫다.</p>
<p>또한 비용과 지연을 quality와 독립된 사후 지표로 보지 말아야 한다. 느린 모델은 timeout과 재시도를 늘려 실제 품질을 떨어뜨릴 수 있고, 비싼 model route는 트래픽 증가 후 우회 정책을 유발할 수 있다. 반대로 output token을 기계적으로 줄이면 reasoning 실패나 parser 실패가 늘 수 있다. 결국 최적화 대상은 토큰 수가 아니라 <strong>완료된 업무 하나가 요구한 총 비용·지연·수정 횟수</strong>다.</p>
<p>마지막으로 offline 점수를 고객이나 경영진에게 일반화해 약속하지 않는다. 평가는 출시할 만큼 위험을 이해했음을 보여 주는 증거이지, 모든 입력에서 같은 결과를 보장하는 증명은 아니다.</p>
<h2 id="체크리스트-또는-연습">체크리스트 또는 연습</h2>
<ol>
<li>운영 중이거나 계획 중인 LLM 기능 하나에 대해 product decision을 한 문장으로 쓰고, primary outcome·safety constraint·operational guardrail을 각각 하나 이상 정한다.</li>
<li>최근 평가 fixture 20건을 normal/high-impact, complete/missing context, current/legacy format으로 분류해 빈 slice를 찾는다.</li>
<li>다음 prompt 또는 model 변경에서 <code>run_id</code>, 모든 component version, 비용·지연을 남기고 baseline과 한 변수만 다르게 비교한다.</li>
<li>high-impact slice가 30건 미만이면 추가 수집 또는 human-reviewed synthetic case를 만든 뒤 hard rollout을 보류한다.</li>
<li>canary용 rollback 조건을 숫자로 작성한다. 예: policy violation 1건, safety metric 1%p 하락, p95 SLO 초과 10분 지속 중 하나면 이전 baseline으로 복귀한다.</li>
</ol>
<p>LLM 평가의 성숙도는 리더보드에서 가장 높은 수치를 얻는 데 있지 않다. <strong>팀이 어떤 이득을 위해 어떤 위험까지 감수할지 먼저 말하고, 변경 전후의 증거로 그 약속을 지키는 데</strong> 있다. 이 원칙이 있으면 모델이 바뀌고 기능이 늘어나도 release 속도와 안전을 서로 반대편에 놓지 않을 수 있다.</p>
]]></content:encoded></item></channel></rss>