본문으로 건너뛰기

© 2026 Molayo

Qiita헤드라인2026. 06. 25. 22:10

AI가 작성한 코드를 매번 '육안'으로 검토하는 것은 한계. 평가(Eval) 시스템을 구축하여 '맡겨서 확인하는' 개발로 전환하기

요약

AI가 생성한 코드의 양이 급증함에 따라 육안 검토의 한계를 지적하며, 이를 해결하기 위한 평가(Eval) 시스템 구축의 필요성을 강조합니다. 인간은 합격/불합격 기준(Rubric)을 설계하고, AI가 채점을 수행하며 인간은 일부를 감사하는 효율적인 워크플로우를 제안합니다.

핵심 포인트

  • 육안 검토는 확장성 부족, 개인 의존성, 회귀 감지 불가, 재현성 문제라는 한계가 있음
  • AI 코드 리뷰의 핵심은 인간이 '기준(Rubric)'을 설계하고 AI가 '채점'을 수행하는 역할 분담임
  • 평가 시스템은 비용과 속도에 따라 4계층 피라미드 구조로 설계해야 함
  • LLM-as-judge를 바로 도입하기보다 결정론적 체크부터 단계적으로 구축할 것을 권장

최근 코드의 상당 부분을 AI에게 맡기는 사람이 늘어났습니다.

Claude Code를 사용하든 Cursor를 사용하든, 함수 하나는커녕 기능 전체를 "좋게 작성해 줘"라는 요청만으로 받는 시대입니다. 생산량은 놀라울 정도로 증가했습니다.

하지만 여기서 솔직하게 생각해 보고 싶습니다.

그 AI의 결과물이 '맞는지' 어떻게 판단하고 계신가요?

아마도 많은 현장의 대답은 이렇지 않을까요. "눈으로 봐서, 그럭저럭 괜찮아 보이면 머지(Merge)하자".

이것을 비난하려는 것은 아닙니다. 저 역시 처음에는 그랬습니다. 오히려 AI가 작성한 양이 적을 때는 육안 검토만으로 충분히 돌아갑니다.

다만, AI의 생산량이 늘어날수록 어느 날 문득 깨닫게 됩니다. 내가 AI의 결과물을 끝없이 채점하는 사람만 되어가고 있다는 사실을요.

구현은 AI가 해주는 시대가 되었는데, 리뷰만 전부 우리에게 남아 있습니다. 게다가 그 양은 계속 늘어납니다. 이건 정말 아깝지 않나요?

오늘은 이 '매번 전부 육안 검토 문제'를 평가(Eval) 시스템으로 만드는 관점으로 해결하는 이야기를 하려 합니다. 추상적인 논의로 끝나지 않고, 복사-붙여넣기로 작동 가능한 최소한의 하네스(Harness)와 프롬프트 예시까지 가져가실 수 있도록 작성했습니다.

먼저, 왜 육안 검토가 한계에 도달하는지 이해해야 합니다. 이 부분을 확실히 알아야 시스템 구축 이야기로 넘어갈 수 있습니다. 이유는 크게 네 가지입니다.

1. 확장성(Scale)이 없다.
AI의 출력은 인간의 수십 배 속도로 증가합니다. 하지만 인간의 눈은 하루 8시간밖에 없습니다. 출력이 10배가 되어도, 눈이 10배 빨라지지는 않습니다. 여기서 수요와 공급이 무너집니다.

2. 개인 의존성(Siloed/属人化)이 생긴다.
"저 사람이 검토하면 괜찮아"라는 말은, 그 사람이 병목 지점(Bottleneck)이 된다는 의미이기도 합니다. 리뷰 기준이 그 사람의 머릿속에만 있으면 팀 전체로 확산되지 않습니다.

3. 조용한 회귀(Regression)를 감지할 수 없다.
여기가 가장 무서운 부분입니다. AI의 출력 품질은 내가 코드를 바꾸지 않았더라도 스스로 변하는 경우가 있습니다. 모델이 업데이트되었거나, 프롬프트를 조금 수정했거나, RAG에 넣는 문서를 교체했을 때. 이런 변화로 어제까지 통했던 케이스가 오늘 무너집니다. 육안으로는 이것을 '실제 운영 환경에서 버그가 터진 후에'야 알게 되는 경우가 많습니다.

4. 재현(Reproduce)할 수 없다.
"전에 이렇게 고장 났었지"를 인간의 기억만으로 관리하는 것은 무리입니다. 같은 실수를 몇 번이고 반복하게 됩니다.

구체적인 사고 사례를 상상해 봅시다.

한 팀이 AI에게 '사용자 입력을 JSON 형태로 정리하는' 처리를 맡겼습니다. 6개월 동안 육안 검토로 문제없이 돌아갔습니다. 어느 날, 사용하던 모델이 새 버전으로 바뀌었습니다. 그러자 아주 가끔씩만

null

을 문자열의 `

핵심은 역할 분담입니다. **인간이 설계하는 것은 「합격/불합격 기준(Rubric)」**입니다. 채점이라는 단순 작업을 스케일링(Scale)하는 것은 AI입니다. 그리고 그 채점이 신뢰할 수 있는지를 인간이 일부만 감사(Audit)합니다.

「전부를 눈으로 확인하는 것」에서 「기준을 설계하고, 채점을 맡기고, 일부만 확인하는 것」으로. 이것이 오늘의 주제입니다.

갑자기 코드로 들어가기 전에, 전체적인 지도를 보여드리겠습니다. 평가는 4계층의 피라미드로 생각하면 정리하기 쉽습니다. 아래로 갈수록 「빠르고 저렴」하며, 위로 갈수록 「똑똑하지만 비쌉니다」.

┌───────────────────────────┐
높음・느림 │ L3: 인간 샘플링 감사 │ ← 5~10%만. 판정의 정밀도를 유지
├───────────────────────────┤
...

순서가 매우 중요합니다. 갑자기 LLM-as-judge부터 만들지 마세요.

먼저 L0의 결정론적 체크(Deterministic check)를 통해, 기계적으로 걸러낼 수 있는 것은 전부 걸러냅니다. 「JSON 형식이 깨짐」, 「필수 필드가 없음」, 「lint 에러 발생」 같은 것들은 AI에게 채점을 맡길 필요조차 없습니다. 빠르고, 저렴하며, 흔들림이 없습니다. 여기서 9할의 사고가 차단됩니다.

그다음, L0에서는 측정할 수 없는 「의미의 질」만을 L2의 judge에게 넘깁니다. 그리고 judge 자체가 신뢰할 수 있는지를 L3의 인간 감사로 정기적으로 확인합니다.

이 순서만 지켜도 평가 비용은 단번에 낮아집니다. 게으른 엔지니어일수록 먼저 가장 저렴한 층을 두텁게 만듭니다.

여기서부터는 실제로 동작하는 것을 만듭니다. 주제는 「자연어 주소를 정해진 JSON 구조로 정형화하는 AI 처리」로 하겠습니다. 범용적인 더미(Dummy) 주제입니다.

먼저, 모범 답안 문제집을 파일로 준비합니다. 처음에는 25~50건이면 충분합니다. 해피 케이스(Happy case)뿐만 아니라, 과거에 실수했던 케이스와 까다로운 에지 케이스(Edge case)를 반드시 포함하는 것이 요령입니다.

[
{
"id": "addr-001",
...

여기서 중요한 것은, addr-002와 같이 이전에 깨졌던 케이스를 반드시 1건씩 자산으로 남겨두는 것입니다. 이것이 회귀 테스트(Regression test)의 본체입니다. 운영 환경에서 아찔한 순간을 맞이할 때마다 한 줄씩 추가하세요. 이것만으로도 내일의 내가 같은 사고를 반복하지 않게 할 수 있습니다.

다음은 기계적으로 흑백을 가리는 검사입니다. AI를 호출하기 전에 먼저 이것으로 걸러냅니다.

import json
def deterministic_checks(raw_output: str, case: dict) -> list[str]:
"""기계적으로 판정 가능한 실패를 반환한다. 빈 리스트라면 합격."""
...

지루하죠? 하지만 이 지루한 함수가 L2 judge를 호출하는 비용의 대부분을 절약해 줍니다. 판정이 빠르고 흔들림 없는 검사를 가능한 한 낮은 계층에 쌓는 것. 이것이 평가 설계의 기본 자세입니다.

L0를 통과한 출력에 대해서만, 의미의 질을 AI가 채점하게 합니다. judge를 호출하는 코드는 놀라울 정도로 얇아도 괜찮습니다.

def judge(input_text: str, model_output: str, llm) -> dict:
"""다른 LLM에게 채점을 맡기고, JSON 판정을 받는다. llm은 임의의 클라이언트."""
prompt = JUDGE_PROMPT.format(
...

판정의 온도(Temperature)는 0에 가깝게 설정합니다. 채점자가 기분에 따라 점수를 바꾼다면 회귀 테스트가 될 수 없으니까요.

핵심은 얇은 코드의 내용이 아니라, 채점 기준(Rubric)을 작성한 프롬프트입니다. 이 부분이 이번의 하이라이트이므로 장을 나누겠습니다.

마지막으로, 이것을 CI에 통합합니다. 점수가 기준 미달이면 머지(Merge)를 중단합니다. pytest를 사용해도 좋고, GitHub Actions라면 다음과 같은 형태가 됩니다.

name: ai-eval-gate
on: [pull_request]
jobs:
...

여기까지 오면, **「AI의 출력이 조용히 저하되더라도, 인간이 알아차리기 전에 CI가 빨간불을 띄우는 상태」**가 됩니다. 운영 장애로 나타나기 전에 검문소에서 멈추는 것이죠. 3주 뒤에 결제 데이터의 불일치를 발견하는 식의 미래가 사라지는 것입니다.

자, 이제부터는 걱정이 많은 분일수록 주의 깊게 봐주셨으면 하는 부분입니다.

LLM-as-judge는 편리하지만, judge 자신도 틀립니다. 게다가 꽤나 독특한 방식으로 틀리곤 합니다. 따라서 「AI가 채점하고 있으니 안심이다」라며 통째로 맡겨버리는 것은 위험합니다. 신뢰할 수 있는 채점자로 키워나가는 절차가 필요합니다.

채점 프롬프트는 모호한 5단계 평가가 아니라, 관점별로 흑백을 가릴 수 있는 형태로 작성합니다. 출력은 JSON으로 고정하여 기계적으로 집계할 수 있도록 합니다.

당신은 코드 출력의 엄격한 리뷰어입니다.
다음의 "입력"과 "모델 출력"을 다음 3가지 관점에서 평가해 주세요.
관대한 점수는 주지 마십시오. 조금이라도 의심스러운 것은 fail로 처리하십시오.
...

"관대하게 점수를 주지 마라", "의심스러우면 fail"이라고 명시하는 것이 포인트입니다. judge(판사)는 내버려 두면 너무 친절한 선생님이 되기 쉽기 때문에, 처음부터 엄격하게 훈육해야 합니다.

judge에게는 알려진 습성이 있습니다. 대표적인 것은 이 3가지입니다.

위치 편향 (Position Bias)… 두 개의 출력을 비교하게 하면, 먼저 제시된 쪽을 높게 평가하기 쉽다. -
冗長性 편향 (Verbosity Bias)… 내용과 상관없이 길고 설명이 많은 출력을 높게 평가하기 쉽다. -
자기 우대 편향 (Self-preference Bias)… 자신(동일한 모델)이 작성한 문장을 호의적으로 채점하기 쉽다. -

대책은 간단합니다. 판정 근거(reason)를 반드시 쓰게 하는 것입니다. 그리고 비교를 시킬 때는 순서를 바꾸어 두 번 물어봅니다. 이것만으로도 훨씬 나아집니다.

가장 효과적인 방법은, 한 명의 채점자에게 의존하지 않고, 여러 명의 judge에게 채점하게 하여 다수결을 취하는 방식입니다. 이를 jury-of-judges라고 부릅니다.

이 태스크를 3명의 독립적인 리뷰어로서 평가해 주세요.
각각 별도로 pass/fail을 판정하고, 마지막에 다수결 결론을 내주세요.
- 리뷰어 A(정확성 중시): {관점 1만을 엄격하게 봄}
...

관점을 의도적으로 나누는 것이 핵심입니다. 같은 시점의 3명보다, 다른 시점의 3명이 놓치는 부분을 더 잘 잡아낼 수 있습니다. 한 명이 놓친 안전성 허점을 안전성 담당자인 B가 잡아내는 식입니다.

그리고 이것을 잊어서는 안 됩니다. judge가 올바르게 채점하고 있는지 인간이 확인하는 공정입니다.

방법은 소박합니다. 인간이 30~50건 정도 직접 pass/fail 라벨을 붙입니다. 나아가 "왜 그렇게 판정했는지" 한 줄 메모를 남깁니다. 그 후에 judge의 판정과 얼마나 일치하는지 확인합니다.

# 캘리브레이션(Calibration)을 위한 질문 방식 (인간 라벨과 대조)
다음 출력을 pass/fail로 판정하고, 판단 이유를 한 문장으로 작성해 주세요.
그 후, 인간의 라벨 "{human_label}"과 당신의 판정이
...

여기서 불일치가 많다면 judge가 잘못된 것이 아니라, 대개 루브릭(Rubric, 기준)의 작성 방식이 모호하기 때문입니다. 인간의 판단 기준을 한 단계만 더 언어화하여 프롬프트에 추가합니다. 이를 몇 번 반복하면 judge의 판정이 인간의 감각과 일치하게 됩니다.

이 "인간이 기준을 연마하고, AI가 채점을 돌리는" 왕복 과정이야말로, 평가를 시스템화한다는 것의 본질입니다.

지금까지의 역할 분담을 한 장으로 정리해 둡니다. AI 시대의 개발이란 결국 이 경계선을 어디에 긋느냐의 싸움이라고 생각합니다.

공정수행 주체내용
합격 기준(루브릭) 설계인간무엇을 정답으로 볼 것인가. 여기가 가장 지적인 작업
골든 세트(Golden Set) 선정인간어떤 케이스를 자산으로 남길 것인가. 사고 사례를 하나씩 추가
결정론적 체크(Deterministic Check) 구현인간 $\rightarrow$ 이후 자동한 번 작성하면 이후에는 기계가 돌림
대량의 출력 채점AI스케일링이 필요한 단순 작업은 AI에게 맡김
채점 감사 (5~10%)인간judge가 폭주하고 있지 않은지 정기적으로 체크
기준 업데이트인간불일치나 누락 사례를 보고 기준을 다시 연마

보시는 바와 같이 인간의 일은 사라지지 않았습니다. 오히려 어렵고 재미있는 부분(기준 설계와 감사)에 집중할 수 있게 됩니다. 채점이라는 소모전에서 해방되어 설계에 머리를 쓸 수 있게 되는 것입니다.

이것이 제가 자주 말하는 "구현자에서 설계·평가·문맥 설계자로"의 정체입니다. 역할이 빼앗기는 것이 아니라, 한 단계 위로 끌어올려지는 감각에 가깝다고 생각합니다.

"전부 다 하기에는 너무 힘들 것 같다"라고 생각하는 분들께. 한꺼번에 하지 않아도 괜찮습니다. 작게 시작하는 것이 정답입니다.

골든 세트를 파일 1개, 5건만 만든다.

지금 AI에게 가장 많이 맡기고 있는 처리에 대해, "이것은 반드시 이렇게 답해야 한다"라는 것을 5건, JSON으로 작성합니다. 다음에 아찔한 상황이 생기면 1건을 추가합니다. 이것만으로 회귀 테스트(Regression Test)의 씨앗이 됩니다. -
결정론적 체크를 딱 하나만 작성한다.

JSON이 깨지지 않았는지, 필수 키가 있는지. 가장 비용이 적게 드는 검사를 하나 CI(지속적 통합)에 넣습니다. 아직 judge는 필요 없습니다. 이것만으로도 사고를 체감하는 빈도가 줄어듭니다. -
judge의 루브릭을 한 장 작성하고, 10건만 인간과 대조해 본다.

엄격한 루브릭 (Rubric)을 작성하고, 인간의 판정과 일치하는지 10건 정도로 확인한다. 차이가 발생하면 기준이 되는 문구를 수정한다. judge를 "육성한다"는 감각을 익히고 나면, 그다음은 확장하는 것뿐입니다.

세 가지 모두 아마 1~2시간이면 착수할 수 있습니다. 완벽할 필요는 없습니다. 65점이면 충분합니다. 오늘 5건의 골든 세트 (Golden Set)를 작성해 두면, 내일의 내가 회귀 (Regression) 상황에서 구원을 받을 것입니다.

AI에게 코드를 작성하게 하는 시대, 진짜 병목 현상 (Bottleneck)은 "생성"이 아니라 "그것이 맞는지 어떻게 보증할 것인가"로 옮겨갔습니다.

그리고 그 보증을 매번 사람이 육안으로 확인하는 것은 이미 양적으로 불가능합니다. 이것은 의지의 문제가 아니라 설계의 문제입니다.

그래서 리뷰를 "시스템"으로 바꿉니다.

기준은 인간이 설계하고, 채점은 AI에게 맡기며, 그 채점을 인간이 일부만 감사 (Audit)합니다. 한 번 구축해 두면, AI의 출력이 조용히 저하되더라도 운영 환경에 나가기 전에 검문소에서 막아줍니다.

이것은 굉장히 게으른 발상입니다. 하지만 좋은 게으름입니다. 땀을 흘리는 것이 아니라, 식은땀을 흘리기 전에 시스템으로 막는 것. 계속 손을 움직이는 것이 아니라, 머리와 AI로 한 번 설계해 두는 것입니다.

매번 채점하며 소모되는 오늘의 나로부터 조금만 졸업하여, 평가를 설계하는 쪽으로 넘어가 보세요.

오늘 골든 세트를 5건 작성한 자신에게, 내일의 자신은 아마 "고마워요"라고 말해줄 것입니다. 그 정도로 가벼운 한 걸음부터 시작해 보지 않겠습니까?

끝까지 읽어주셔서 감사합니다.

AI 자동 생성 콘텐츠

본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0