AI 프롬프트, 좋아졌는지 어떻게 알 수 있을까?

평가를 처음 접하는 사람을 위해 시험 문제와 채점 기준을 만들고, build-eval과 hillclimb으로 프롬프트를 개선하는 과정을 설명합니다. 학습·테스트 분리, 대화 평가, 데이터셋 관리까지 예시로 살펴봅니다.

프롬프트를 고친 뒤 AI의 답변이 더 좋아 보이는 순간이 있다. 하지만 몇 번의 성공만으로 다른 요청에서도 좋아졌다고 판단하기는 어렵다. 이 글은 평가를 처음 접하는 사람이 무엇을 준비하고, 어떤 결과를 확인하며, 언제 변경을 채택해야 하는지 이해하도록 돕는 입문서다.

설명에는 이메일 분류와 예약 대화를 사용한다. 예시의 수치와 파일명은 원리를 설명하기 위한 것이며, 보편적인 권장값이나 실제 실험 결과가 아니다. 실행 절차는 Claude Code에 설치한 claude-api 스킬의 /claude-api build-eval과 /claude-api hillclimb을 기준으로 설명한다. 명령은 해당 스킬이 제공하며, 세부 동작은 설치 버전에 따라 달라질 수 있다.

1. 프롬프트를 바꿨는데, 정말 좋아진 걸까?

고객 문의를 담당 부서로 보내는 AI를 만든다고 생각해 보자. AI가 “환불하고 싶어요”를 기술지원팀으로 잘못 보냈다. 그래서 프롬프트에 “환불이라는 말이 나오면 결제팀으로 보내라”는 규칙을 추가했다. 다시 해보니 환불 문의는 결제팀으로 간다. 한 가지 실수는 고친 셈이다.

그런데 “환불 신청 페이지에 로그인할 수 없어요”라는 문의도 결제팀으로 보낸다면 어떨까? 이 문의는 로그인 문제를 해결할 기술지원팀으로 가야 한다. 환불 문의 하나를 맞히는 대신 다른 문의를 틀리게 된 것이다.

환불 문의 수정 전후의 분류 결과 비교

따라서 방금 고친 문의 하나만 다시 넣어보지 않고, 환불·로그인 등 여러 문의를 고치기 전과 후에 같은 조건으로 넣어본다. 각 문의가 어느 부서로 가야 하는지도 미리 정해 둔다. 이렇게 결과를 비교하는 과정이 평가, 즉 eval이다. 프롬프트의 문장이 그럴듯한지를 넘어 실제 동작이 좋아졌는지 판단할 근거를 만든다.

다른 요청에서 생기는 오류와 별개로, 같은 요청의 답변이 흔들리는 문제도 있다. 프롬프트를 바꾸지 않아도 첫 번째 실행에서는 틀리고 두 번째 실행에서는 맞힐 수 있다. 수정 전후 답변을 한 번씩만 비교하면 우연히 잘 나온 결과를 개선으로 착각할 수 있다.

이 글에서 평가 대상 AI는 문의를 분류하거나 예약 요청에 답하는 서비스의 AI다. Claude Code는 평가 도구를 만들고 서비스의 프롬프트를 수정하는 작업자다. 예약 AI가 실패 사례를 보고 스스로 학습하는 것이 아니라, Claude Code가 실패를 분석해 지침을 고치고 그 지침으로 예약 AI를 다시 실행한다.

전체 과정은 다음과 같다.

prompt-eval-overview

build-eval은 반복해서 사용할 평가를 만드는 과정을 돕는다. hillclimb은 그 평가를 기준으로 변경과 검증을 반복하는 과정을 돕는다.

2. 무엇을 ‘잘한다’고 볼 것인가?

먼저 평가할 기능을 하나로 좁힌다. “우리 AI가 똑똑한가?”는 범위가 너무 넓다. “문의 내용을 읽고 담당 부서를 올바르게 고르는가?”나 “필요한 정보를 확인한 뒤 정확한 예약을 만드는가?”처럼 관찰 가능한 행동으로 바꾼다.

기능 잘 수행했다는 의미 확인할 결과
이메일 분류 문의에 맞는 부서를 선택한다. 실제 부서와 기대 부서의 일치 여부
문서 요약 핵심 내용을 빠뜨리지 않고 없는 사실을 만들지 않는다. 원문과 요약의 내용 관계
예약 대화 필요한 정보를 모으고 동의를 받은 뒤 정확히 예약한다. 대화 과정, 도구 호출, 생성된 예약

예약 AI는 시간 조회 도구와 예약 생성 도구를 사용할 수 있다. 전자는 가능한 시간을 확인하고, 후자는 실제 예약을 만든다. AI가 이 기능에 날짜·시간·인원 같은 값을 전달해 실행을 요청하는 것을 도구 호출이라고 한다. 예약 평가에서는 답변뿐 아니라 이 호출과 생성된 예약도 확인한다.

품질 외에 지켜야 할 조건도 정한다. 예를 들어 정확도를 높이더라도 응답 시간이 지나치게 길어지면 서비스에는 도움이 되지 않을 수 있다. 비용 절감이 목표라면 반드시 유지해야 하는 품질 수준을 함께 정한다.

평균 점수 하나로 모든 것을 표현하려 하지 않아도 된다. 전체 정확도와 함께 중요한 유형의 오류, 응답 시간, 비용을 따로 기록하면 무엇을 얻고 무엇을 잃었는지 판단하기 쉽다.

3. 시험 문제 만들기: 평가 데이터셋

평가 데이터셋은 AI에게 풀게 할 시험 문제의 모음이다. 모델을 재학습시키기 위한 대규모 데이터가 꼭 필요한 것은 아니다. 기존 기능에 넣을 입력과 결과를 판단할 기준을 준비하는 것이 출발점이다.

분류 문제의 사례 한 건은 다음처럼 구성할 수 있다.

항목 내용
식별자 billing-01
입력 “구독을 해지했는데 이번 달에도 결제됐어요.”
기대 결과 결제 부서
유형 구독 해지 후 청구 문의

입력은 사용자 문장만을 뜻하지 않는다. 기능이 이전 대화, 첨부파일, 사용자 설정, 현재 날짜 등을 참고한다면 평가에도 필요한 맥락을 함께 제공해야 한다. “내일 예약해 줘”라는 요청을 평가하면서 기준 날짜가 달라지면 서로 다른 문제를 푸는 셈이다.

사례는 실제 사용자 요청에서 찾는 것이 좋다. 그다음으로 버그 보고와 지원 티켓을 활용하고, 자료가 부족하면 사람이 대표 사례를 몇 개 작성한다. AI가 사례를 추가로 만들 수 있지만, 실제 요청의 형태와 난이도를 참고하게 하고 사람이 결과를 읽어야 한다. 보관할 수 있는 자료인지 확인하고 개인정보는 평가에 필요하지 않다면 제거한다.

쉬운 문제만 모으면 개선할 여지가 보이지 않는다. 현재 모델이 틀리는 문제만 모으면 그 모델 특유의 약점에 편중될 수 있다. 사례를 고를 때는 요청이 들어오는 빈도와 실패했을 때의 영향을 함께 본다.

흔한 요청은 평소 사용자 경험을 확인할 수 있게 포함한다. 드물어도 잘못 실행하면 피해가 큰 요청은 별도로 포함하고, 그 유형의 실패 여부를 따로 본다. 예약 요청뿐 아니라 “예약하지 말고 가능한 시간만 알려 달라”는 요청도 그런 사례다. 중요한 예외를 많이 넣은 평가의 전체 정확도를 실제 서비스의 평균 성능으로 그대로 해석하지는 않는다.

사례를 검토할 때는 “이런 요청이 실제로 들어오는가?”, “필요한 맥락이 있는가?”, “두 사람이 읽어도 기대 결과에 동의할 수 있는가?”를 확인한다. 개수는 그다음 문제다.

4. 채점 기준 만들고 검증하기

코드로 확인할 수 있는 결과

이메일 분류처럼 가능한 답이 정해져 있다면 실제 결과와 정답을 비교한다. JSON 형식, 필수 항목, 도구에 전달된 인자, 생성된 데이터도 코드로 확인할 수 있다.

기대하는 부서: 결제
AI가 선택한 부서: 결제
판정: 통과

표현 차이를 허용할지 먼저 정해야 한다. 결제팀과 결제가 같은 의미라면 이를 처리하지 못하는 채점기는 올바른 답을 틀렸다고 판정할 수 있다. 다만 서비스가 정확한 식별자 billing을 요구한다면 형식 위반도 실제 오류가 된다.

AI의 판단이 필요한 답변

고객에게 보내는 안내문은 문장이 달라도 좋은 답변일 수 있다. 이때는 별도의 AI를 심사자로 사용해 답변과 채점 기준을 함께 읽게 할 수 있다. 채점받는 모델과 다른 모델을 사용하고, 판단 근거도 남긴다.

“친절함을 5점 만점으로 평가하라”보다 다음처럼 확인 가능한 조건을 제시하는 편이 기준을 맞추기 쉽다.

정답 문장 하나를 복제하게 만들기보다 허용되는 답의 범위와 지켜야 할 조건을 정의한다. 두 버전을 비교하는 것이 목적이라면 어느 쪽이 기존 버전인지 숨기고 무작위 순서로 제시해 더 나은 답을 고르게 하는 방법도 있다.

채점기를 사람이 검증하기

전체 평가를 돌리기 전에 몇 건만 채점하고 입력, 답변, 점수, 판정 이유를 함께 읽는다. 사람이 모든 결과를 영구적으로 채점하는 것이 아니라 자동 채점기가 원하는 기준을 적용하는지 확인하는 단계다.

예를 들어 고객이 환불 가능 여부를 물었고 AI가 “결제 내역을 확인한 뒤 안내하겠습니다”라고 답했다. 채점기가 “즉시 환불하지 않았으므로 실패”라고 판정한다면, 서비스 정책에 따라 답변보다 채점 기준을 고쳐야 할 수 있다.

AI를 채점기로 쓴다고 사람이 원하는 품질 기준까지 자동으로 결정되는 것은 아니다. 무엇을 통과로 볼지는 사람이 정하고, 채점기가 그 기준을 일관되게 적용하는지 검증한다.

5. 수정에 참고할 문제와 확인할 문제 나누기

왜 문제를 나누는가?

틀린 시험 문제를 보고 공부한 뒤 그 문제를 다시 맞혔다고, 처음 보는 문제도 잘 푼다고 할 수는 없다. 프롬프트 개선도 마찬가지다. 예약 AI가 다음처럼 실수했다고 하자.

사용자: 예약하지 말고 가능한 시간만 알려 줘.
예약 AI: [예약 생성] → 실패

프롬프트를 수정하는 Claude Code에게 이 실패를 보여 주면, “조회만 요청하면 예약 생성 도구를 호출하지 않는다”는 규칙을 추가할 수 있다. 이후 같은 요청에서 예약을 만들지 않았다면 기존 오류를 고쳤다는 증거가 된다. 이 사례를 계속 평가에 포함하면 같은 오류가 재발하는지도 확인할 수 있다.

하지만 수정에 사용한 사례를 별도로 남겨 둔 확인용 사례 목록에 옮겨도, Claude Code가 이미 본 문제라는 사실은 바뀌지 않는다. 새로운 요청에도 규칙이 통하는지 확인하려면 수정할 때 보여 주지 않았던 별도의 사례가 필요하다.

따로 남겨 둔 확인용 문제:
“아직 확정은 안 할게요. 내일 오후에 빈자리가 있나요?”

기대 행동:
가능한 시간을 안내하고, 예약은 만들지 않는다.

이 요청에서도 올바르게 행동하면 규칙이 다른 표현에도 적용된다는 추가 근거가 된다. 이처럼 참고한 사례에서 배운 규칙이 보지 않은 사례에도 통하는 것을 일반화라고 한다. 한 문제만으로 모든 상황에서 일반화한다고 판단할 수는 없으므로, 대표적인 요청들을 별도로 남겨 두고 확인한다.

사례의 용도 확인하려는 질문
수정에 사용한 실패와 재발 확인용 사례 이 오류를 고쳤고, 다시 생기지 않는가?
수정에 사용하지 않은 확인용 사례 보지 않은 요청에도 잘 대응하는가?

앞서 “‘두 번’이면 결제 부서”라는 규칙은 참고한 문의에는 맞았지만 로그인 문의에는 통하지 않았다. 이런 현상을 과적합이라고 한다. 이를 알아보려면 수정에 참고하는 문제와 내용은 보여 주지 않고 확인에 사용하는 문제를 구분해야 한다.

수정용 사례와 확인용 사례

prompt-eval-train-test

구분 역할
학습 집합(train) · 수정용 사례 Claude Code가 사례와 실패 기록을 읽고 프롬프트를 고칠 때 참고한다.
테스트 집합(test) · 확인용 사례 문제 내용은 수정에 제공하지 않고, 고친 프롬프트를 실행해 결과를 확인한다.

여기서 학습은 모델의 가중치를 재학습한다는 뜻이 아니다. Claude Code가 프롬프트나 설정을 고칠 때 참고한다는 뜻이다. 테스트 사례는 실행을 위해 평가 프로그램과 평가 대상 AI에는 입력하지만, 프롬프트를 수정하는 Claude Code에게는 내용과 상세 실패 기록을 보여 주지 않는다.

이 글의 간단한 구성에서는 두 집합을 사용하고, 테스트 점수로 반복 중 변경을 비교한다. 문제 내용을 숨겨도 점수를 보고 변경을 계속 선택하면 그 집합에 맞춰지는 위험은 남는다. 별도로 남겨 둔 문제로 마지막 성능을 확인하는 더 엄격한 방법은 9절에서 설명한다.

몇 개를 준비하고 어떻게 나눌까?

고정된 정답은 없다. 공식 build-eval 지침은 첫 평가에 15~100개 정도를 출발 범위로 제시하지만, 반복 개선까지 할 경우에는 감지하려는 개선 폭에 맞춰 사례 수와 반복 수를 정하도록 한다. 다음은 소규모 실험을 설명하기 위한 분할 예시다.

전체 사례 학습 집합 테스트 집합
50개 30개 20개
100개 60개 40개

이 비율이 표준은 아니다. 테스트가 20개이고 사례마다 한 번씩 실행한다면 한 문제를 더 맞히는 것만으로 점수가 5%포인트 변한다. 작은 개선을 확실히 판단하려면 더 많은 사례와 적절한 반복, 불확실성 분석이 필요하다.

학습·테스트 양쪽에 주요 요청 유형이 포함되도록 나눈다. 테스트 집합에 특수하고 어려운 사례만 몰아넣지 않는다. 같은 원본에서 나온 거의 동일한 사례는 한쪽에 모아 둔다. 예를 들어 같은 문의의 단어만 바꾼 문장을 양쪽에 넣으면, 수정에 참고하지 않은 새로운 상황을 시험하는 효과가 줄어든다.

사례가 너무 적으면 억지로 나누기보다 전체 사례로 문제를 찾는 탐색부터 할 수 있다. 다만 이때 얻은 점수는 이미 참고한 문제에서의 결과이므로 새로운 요청에서도 개선됐다는 증거로 과장하지 않는다.

6. 평가를 실행하고 결과를 기록하기

실행기와 결과 기록

문제와 채점 기준, 두 집합을 준비했으면 실제 서비스의 기능을 호출하는 실행기를 만든다. 평가를 위해 새로운 플랫폼부터 도입할 필요는 없다. 기존 도구가 있다면 재사용하고, 없다면 프로젝트 안의 작은 스크립트와 결과 파일로 시작할 수 있다.

다시 실행하고 비교할 수 있도록 다음 자료를 함께 관리한다.

산출물 역할
사례 데이터 입력, 기대 결과 또는 평가 조건, 유형을 보관한다.
채점기 출력이나 실행 결과를 기준에 따라 판정한다.
실행기 기존 기능을 각 사례로 실행하고 결과를 저장한다.
실행 기록 입력, 실제 응답, 도구 호출, 오류 등을 추적한다.
결과 보고서 전체 점수와 사례별 판정 근거를 사람이 살펴보게 한다.

다음은 파일 구성 예시이며, build-eval 스킬이 이 파일명을 그대로 만든다는 뜻은 아니다.

evals/
├── cases.json       # 입력과 평가 조건
├── grade.ts         # 채점기
├── run.ts           # 평가 실행기
└── results/
    ├── results.jsonl
    └── report.html

실행기의 기본 동작은 “사례 읽기 → 기존 기능 호출 → 결과 채점 → 기록 저장”이다. 실제 응답 품질을 알고 싶다면 실제 모델 호출을 평가해야 한다. 모델의 답을 미리 정한 가짜 응답으로 대체한 테스트는 주변 코드 확인에는 유용하지만 모델 품질의 증거가 되지는 않는다.

보고서에는 다음과 같은 내용이 표시된다.

사례 기대 결과 실제 결과 판정
구독을 해지했는데 또 결제됐어요. 결제 결제 통과
비밀번호를 잊어버렸어요. 계정 기술지원 실패

여러 차례 이어지는 대화

예약 AI는 사용자의 요청을 듣고, 부족한 정보를 물어보고, 동의를 받은 뒤 예약해야 한다. 한 번의 답변만 확인해서는 이 과정을 제대로 수행하는지 알기 어렵다. 대화 평가는 확인하려는 범위에 따라 두 가지 방법으로 진행할 수 있다.

방법 1: 대화의 한 지점만 확인한다.
미리 작성한 이전 대화 → 예약 AI가 다음 행동을 생성한다 → 채점한다

방법 2: 대화 전체를 진행한다.
사용자 역할 ↔ 예약 AI → 대화 기록과 예약 결과를 모은다 → 채점한다

첫 번째 방법은 이전 대화를 고정하고 다음 행동을 평가하는 것이다. 아래 대화를 미리 준비해 평가 대상 AI에게 입력한다.

[미리 준비한 대화]
사용자: 내일 예약해 줘.
AI: 몇 시에 몇 명으로 예약할까요?
사용자: 오후 3시에 두 명이요.

[여기서 평가 대상 AI를 실행한다]
AI: 내일 오후 3시, 두 명으로 예약할까요?

이 시험에서는 예약 전에 최종 동의를 구하는지 확인한다. 동의를 받지 않고 예약 생성 도구를 호출하면 실패다. 특정 상황에서 다음 행동이 적절한지 확인하기 쉽지만, 앞부분은 미리 작성한 대화이므로 AI가 처음부터 대화를 잘 이끌었다는 증거는 아니다.

두 번째 방법은 처음부터 끝까지 대화를 진행하며 평가하는 것이다. 사용자 역할을 맡은 사람이나 별도의 AI가 평가 대상 AI의 질문에 답한다.

사용자 역할 AI는 대화를 이어 주고, 채점기는 그 과정과 결과를 검사한다. 사용자 역할에는 다음처럼 목표와 행동 조건을 준다.

자동으로 평가한다면 앞에서 설명한 실행기가 두 AI를 번갈아 호출한다. 사용자 역할 AI에는 위 시나리오를 주고, 예약 AI에는 실제 서비스에서 사용하는 프롬프트와 시간 조회·예약 생성 도구를 준다. 실행기는 사용자 메시지를 예약 AI에게 전달하고, 예약 AI의 질문을 사용자 역할 AI에게 전달하는 일을 반복한다. 예약 AI에게 사용자 역할의 시나리오를 미리 보여 주지는 않는다.

conversation-eval-flow

다음은 이 조건으로 진행될 수 있는 대화 예시다. 예약 AI의 답변은 미리 정한 문장이 아니라 실행할 때 생성되는 응답이다. 실행기는 대화가 끝나지 않는 경우에 대비해 최대 대화 횟수도 정한다.

사용자 역할: 내일 예약해 줘.
예약 AI: 몇 시에 예약할까요?
사용자 역할: 오후 3시요.
예약 AI: 몇 명인가요?
사용자 역할: 두 명이요.
예약 AI: 내일 오후 3시, 두 명으로 예약할까요?
사용자 역할: 네.
예약 AI: [예약 생성 도구 호출]

실행기는 대화 기록과 도구 호출을 저장한다. 채점기는 날짜·시간·인원을 모두 확보했는지, 동의를 받은 뒤 예약을 생성했는지, 올바른 인자로 예약 생성 도구를 호출했는지 확인한다. 실제 상태를 확인할 수 있다면 테스트 환경에 생성된 예약까지 검사한다. 여기서 테스트 환경은 실제 고객의 예약에 영향을 주지 않도록 평가용 예약을 만드는 별도 환경이다. “내일”의 의미가 달라지지 않도록 기준 날짜와 시간대도 고정한다.

예를 들어 기준 날짜를 2026년 10월 8일, 시간대를 한국 시간으로 고정했다면 채점 결과는 다음처럼 읽을 수 있어야 한다.

검사 항목 확인한 증거 판정
필요한 정보를 모았는가? 대화에서 날짜·오후 3시·두 명을 확보했다. 통과
동의 후 예약을 생성했는가? 사용자 “네” 다음에 예약 생성 도구를 호출했다. 통과
도구에 올바른 값을 줬는가? 날짜 2026-10-09, 시간 15:00, 인원 2를 전달했다. 통과
예약이 생성됐는가? 테스트 환경에 같은 내용의 예약이 존재한다. 통과

예약 AI가 “예약했습니다”라고 답해도 도구를 호출하지 않았거나 다른 시간으로 예약했다면 실패다. 이처럼 대화의 문장과 실행 결과를 함께 검사하는 것이 전체 대화 평가다.

사용자 역할 AI가 지나치게 협조적이거나 시나리오에서 벗어나면 평가가 실제 상황을 반영하지 못할 수 있다. 따라서 목표와 제약을 정하고, 생성된 대화 일부를 사람이 읽어 실제 사용자와 비슷하게 행동하는지 확인한다.

build-eval로 준비하기

Claude Code에서 claude-api 스킬을 사용할 수 있는 상태라면 다음 명령으로 시작한다.

/claude-api build-eval

평가할 기능과 사용할 수 있는 자료를 알려 준다. 예를 들어 “고객 문의를 담당 부서로 분류하는 기능을 평가하고 싶다. 익명화한 실제 문의 사례가 있다”고 설명할 수 있다. Claude Code는 기능의 입력과 출력, 사례의 출처, 채점 방법을 확인하고 사용자가 사례와 채점 방식을 검토하도록 돕는다. 실제 모델을 호출하는 실행에는 비용이 발생하므로 실행 규모와 예산도 확인한다.

이 명령은 앞에서 설명한 사례·채점기·실행기와 검토 절차를 준비하도록 돕는다. 만든 평가로 현재 버전의 성능을 측정하는 것이 다음 단계다.

7. 현재 실력과 응답의 변동 측정하기

먼저 기존 프롬프트의 점수를 기록한다

평가를 준비했으면 프롬프트를 고치기 전에 기존 버전을 학습·테스트 두 집합에서 각각 실행한다. 이 결과가 기준점인 베이스라인이다. 예를 들어 테스트 사례 30개 중 24개를 맞혔다면 해당 집합의 정확도는 80%다. 이후 변경도 같은 사례와 기준으로 평가하여 비교한다.

같은 평가를 반복하면 무엇이 보일까?

AI는 같은 입력에도 다른 결과를 낼 수 있다. 이를 확인하려면 같은 문제 묶음을 같은 설정으로 여러 번 실행해 본다. 예를 들어 예약 요청 A·B·C를 준비하고, 세 문제를 모두 실행하는 평가를 세 번 반복했다고 하자. 표의 각 칸은 대화 한 건을 끝까지 실행한 뒤 얻은 최종 판정이다. 다음은 원리를 설명하기 위한 예시이며, 세 문제나 세 번이 권장 규모라는 뜻은 아니다.

문제 1회차 2회차 3회차
A: 일반 예약 성공 성공 성공
B: 시간 변경 성공 실패 성공
C: 예약 없이 시간 조회 실패 실패 실패
회차별 정확도 67% 33% 67%

이 표는 두 방향으로 읽을 수 있다.

총 9건의 평가 결과를 얻었지만, 서로 다른 문제는 3개다. 반복은 같은 요청에서 답변이 얼마나 흔들리는지 알려 주고, 새로운 문제는 다른 요청도 처리할 수 있는지 알려 준다. 대화 문제 한 건을 평가하는 동안에는 AI를 여러 번 호출할 수 있다. 평가 실행 횟수와 모델 호출 횟수는 구분한다.

기록에도 이 구분을 남긴다. 각 결과에 문제 ID, 프롬프트 버전, 반복 번호를 저장하면 같은 문제의 반복 결과를 묶고, 기존 버전과 수정 버전을 같은 문제끼리 비교할 수 있다.

작은 점수 차이는 불확실성과 함께 본다

신뢰구간은 이런 측정의 불확실성을 정해진 통계적 방법과 가정 아래 범위로 나타낸 것이다. 일부 문제에서 측정한 점수만으로 실제 요청 전체에서의 성능을 정확히 알 수는 없다. 점수와 함께 불확실성의 범위를 보고, 두 버전을 비교할 때는 점수 차이의 불확실성도 확인하면 작은 상승을 얼마나 조심스럽게 해석해야 하는지 판단하는 데 도움이 된다.

독자가 먼저 할 일은 각 문제의 반복 결과를 같은 문제 ID로 보관하는 것이다. 불확실성을 계산하는 도구에도 이 정보를 전달해 A의 세 결과를 서로 다른 문제 세 개로 취급하지 않도록 한다. 신뢰구간의 계산 방법은 평가 설계에 맞게 선택해야 한다. 여기서는 문제 단위의 묶음을 유지한다는 원칙을 알아 두고, 통계 계산 절차는 별도로 준비한다.

동작 실패와 실행 오류를 구분한다

모델의 실패와 실행 오류도 구분한다. API 시간 초과, 잘린 답변, 채점기 오류를 그대로 오답에 섞으면 무엇을 개선해야 하는지 불분명해진다. 오류율과 품질 점수를 따로 확인하고, 비교하는 두 버전의 환경과 실행 조건을 기록한다.

8. hillclimb으로 한 번에 하나씩 개선하기

실행 가능한 평가가 준비되면 다음 명령으로 개선을 시작한다.

/claude-api hillclimb

한 번의 개선 작업 안에서는 학습·테스트 집합과 채점 기준을 고정한다. 문제와 프롬프트를 함께 바꾸면 무엇 때문에 점수가 달라졌는지 알기 어렵다.

목표와 수정 범위를 먼저 정한다. “분류 정확도를 높이되 시스템 프롬프트만 바꾼다”처럼 범위를 좁히면 결과를 해석하기 쉽다. 모델 선택, 추론 수준, 도구 설명, 실행 코드도 대상이 될 수 있지만, 한 반복에서는 하나의 가설을 검증하는 변경에 집중한다.

예를 들어 환불 문의의 오분류가 반복된다면 담당 부서의 정의가 불명확하다는 가설을 세운다. 부서 정의를 수정한 뒤 평가를 다시 실행한다. 문서의 여러 문장을 고쳤더라도 하나의 원인을 해결하는 변경이라면 하나의 실험으로 볼 수 있다.

prompt-eval-improvement-loop

프롬프트를 수정한 뒤, 수정에 참고한 학습 문제뿐 아니라 따로 남겨 둔 테스트 문제에서도 성능이 좋아졌는지 확인한다. 학습 점수는 올랐지만 테스트 점수가 떨어졌다면, 참고한 문제에만 맞춰진 것은 아닌지 살펴보고 변경을 되돌릴지 판단한다.

다만 학습 점수만 올랐다고 곧바로 과적합으로 확정하거나, 모든 실험에서 두 점수가 반드시 함께 올라야 한다고 이해해서는 안 된다. 점수 차이가 응답의 자연적인 변동보다 큰지, 목표가 품질인지 비용인지, 유지해야 할 조건을 충족했는지 함께 판단한다. 비용 절감이 목표라면 품질이 허용 범위에서 유지되면서 비용이 낮아지는 변경도 성공이다.

변경을 몇 차례 시도해도 점수가 정체되면 남은 실패를 원인별로 살펴본다.

원인 예시 대응
실제 동작 오류 중복 청구 문의를 기술지원으로 보낸다. 원인이 되는 지침이나 동작을 수정한다.
모호한 문제 결제와 로그인 문의를 함께 했는데 우선순위가 없다. 기대 동작을 정하고 사례를 명확히 한다.
채점 오류 유효한 답을 표현 차이 때문에 실패로 처리한다. 채점기를 수정한다.
실행 오류 API 요청이 시간 초과됐다. 실행 환경을 확인한다.

점수가 낮다는 사실만으로 프롬프트를 계속 고치지 않는다. 평가 자체에 오류가 있다면 먼저 바로잡고, 기존 버전과 개선 버전을 같은 수정된 기준에서 다시 측정한다.

9. 최종 결과를 판단하고 적용하기

반복 결과를 비교해 적용할 버전을 고른다

마지막으로 시도한 버전이 가장 좋은 것은 아니다. 아래는 같은 학습·테스트 집합에서 측정한 반복 결과의 설명용 예시다.

버전 변경 학습 점수 테스트 점수
기준 버전 변경 없음 70% 70%
1차 수정 부서의 담당 범위를 명확히 한다. 85% 82%
2차 수정 특정 실패의 표현에 맞춘 규칙을 추가한다. 95% 76%

표의 차이가 충분히 신뢰할 만하고 다른 조건도 충족한다면 1차 수정 버전을 선택할 이유가 있다. 2차 수정은 참고한 문제에서는 더 잘하지만, 테스트에서는 오히려 나빠졌다.

최종 선택은 처음 정한 목표를 따른다. 품질이 목표라면 비용·응답 시간 등의 제약을 지키면서 품질이 좋은 버전을 선택한다. 비용이 목표라면 필요한 품질을 유지하는 버전 중 비용이 낮은 것을 선택한다. 개선이 확인되지 않으면 원래 버전을 유지하는 것도 정상적인 결과다.

별도의 최종 확인이 필요한 경우

앞의 표는 반복 중 변경을 선택할 때 참고한 점수다. 테스트 문제의 내용을 숨겼더라도 그 점수가 가장 높은 변경을 계속 선택하면, 그 문제 묶음에서 우연히 잘 나온 버전을 고를 수 있다. 따라서 이 점수를 한 번도 참고하지 않은 새 문제에서의 성능과 똑같이 해석하지 않는다.

실제 적용 여부를 더 엄격히 확인해야 한다면 문제를 세 역할로 나눈다.

역할 언제 사용하는가?
학습 집합 · 수정용 사례와 실패 기록을 읽고 프롬프트를 고친다.
검증 집합 · 반복 비교용 문제 내용은 수정에 제공하지 않고, 점수로 변경을 비교하고 선택한다.
최종 테스트 집합 · 마지막 확인용 후보를 정할 때까지 내용과 점수를 모두 남겨 두고, 선택을 마친 뒤 평가한다.

이 구성에서는 앞의 표에 있는 반복 비교용 ‘테스트 점수’를 ‘검증 점수’로 구분한다. 최종 확인에서는 선택한 프롬프트와 기존 프롬프트를 같은 최종 테스트 집합으로 평가한다. 그 결과를 보고 다시 프롬프트를 고쳤다면, 그 집합은 이제 수정이나 선택에 참고한 자료다. 더 이상 손대지 않은 최종 시험으로 취급하지 않는다.

변경 이유와 결과를 남기고 운영에서 관찰한다

hillclimb은 선택한 변경뿐 아니라 반복별 패치, 변경 이유, 평가 기록, 실행 상태와 최종 보고서를 남긴다. 기본 결과 저장 위치는 .claude/hillclimb/<평가 이름>/이며, 기존 프로젝트 구조를 사용할 수도 있다. 보고서에서는 다음을 읽을 수 있어야 한다.

평가에서 이긴 버전도 실제 사용자에게 적용한 뒤에는 관찰이 필요하다. 평가 사례가 실제 요청 전체를 완벽하게 대표하지는 않기 때문이다. 변경의 적용 여부는 점수와 판정 근거를 함께 보고 결정한다.

10. 평가를 지속적으로 관리하기

사례를 추가하거나 제외할 때

한 번의 비교에서는 문제를 고정하되, 운영 중에는 새 요청과 실패 사례를 모아 다음 평가 버전에 반영한다.

상황 처리
실제 서비스에 새로운 요청 유형이 생긴다. 다음 평가 버전에 대표 사례를 추가한다.
드물지만 영향이 큰 오류가 발생한다. 재발 확인용 사례를 추가한다.
거의 같은 유형의 사례가 계속 쌓인다. 대표성을 유지하면서 중복을 줄인다.
기대 정답이 잘못됐거나 문제가 모호하다. 수정하고 변경 이력을 남긴다.
기능이 없어져 더는 관련 없는 사례가 된다. 활성 평가에서 제외하고 이력은 보관한다.
모델이 계속 틀린다. 그 이유만으로 제외하지 않는다.

보관할 사례와 매번 실행할 사례를 구분한다

새 실패를 보관한다고 수집한 사례를 모두 매번 실행할 필요는 없다. 자주 실행하는 대표 평가와 중요한 과거 오류의 재발 확인용 검사를 나눌 수도 있다.

서비스 범위가 넓어지거나 더 작은 차이를 판단해야 한다면 평가 규모를 늘린다. 비슷한 사례를 무제한 누적하기보다, 새로운 유형을 포함하고 중복을 줄이면서 대표성을 유지한다.

수정에 사용한 실패는 기록을 남긴다

5절에서 본 예약 실패처럼 수정하는 Claude Code에게 보여 준 사례는 학습 자료와 재발 확인용으로 보관한다. 어느 프롬프트를 고칠 때 참고했는지 기록하면, 나중에 그 사례를 보지 않은 테스트 문제로 잘못 취급하는 것을 막을 수 있다.

테스트 집합에서 발견한 실패라도 내용을 읽고 수정에 사용했다면 그 사실을 기록한다. 새 요청에 대한 성능을 확인할 때는 수정과 선택에 사용하지 않은 사례를 별도로 남겨 둔다.

평가가 바뀌면 베이스라인도 다시 측정한다

운영 중에는 새 사례를 모으고, 다음 평가 버전을 만들 때 구성을 갱신한다. 여기서 평가 버전은 문제와 채점 기준의 버전이다. 평가를 갱신한다고 프롬프트까지 바꾸는 것은 아니다.

평가를 갱신하면 저장해 둔 베이스라인도 다시 측정해야 한다. 예를 들어 기존 프롬프트를 평가 v1로 측정해 80%라는 기록을 남겼다고 하자. 나중에 새 사례를 추가해 평가 v2를 만들고, 수정한 프롬프트만 v2로 실행했더니 85%가 나왔다.

기존 점수가 이미 있으니 두 숫자를 바로 비교하고 싶을 수 있다. 하지만 80%는 옛 시험에서 받은 점수다. 시험 문제가 달라졌으므로, 85%가 프롬프트 수정 덕분에 오른 것인지 문제 구성 때문에 달라진 것인지 구분할 수 없다. 기존 프롬프트도 v2에서 다시 실행해 새 기준점을 만들고, 수정한 프롬프트의 v2 결과와 비교한다.

prompt-eval-dataset-versions

평가의 가치는 점수 자체보다 변경을 선택할 때 사용할 수 있는 근거에 있다. 중요한 요청을 대표하는 사례와 믿을 만한 채점 기준을 유지해야 반복 개선의 결과도 실제 서비스에 도움이 된다.

참고 자료

명령과 기본 산출물은 2026-09-29에 확인한 지침을 기준으로 한다. 데이터셋 버전 관리와 일부 예시는 원문을 이해하고 실무에 적용하기 위한 보충 설명이다.