개념
케이스를 쓰는 사람에서 기준을 쓰는 사람으로
지금까지 QA의 대표 산출물은 테스트 케이스였다. 입력·절차·기대 결과를 한 줄씩 적고, 그것을 사람이나 스크립트가 실행했다. AI 에이전트가 테스트를 설계하고 실행하는 조직에서는 이 분업이 바뀐다. 케이스를 펼치는 일은 AI가 하고, QA는 AI가 무엇을 기준으로 펼치고 무엇을 기준으로 판정할지를 쓴다.
이 변화가 "QA가 할 일이 줄었다"는 뜻은 아니다. 오히려 어려워졌다. 사람이 쓴 케이스는 쓴 사람의 머릿속 맥락이 빈칸을 메워 줬다. "로그인 실패 시 적절한 오류 메시지 표시" 같은 기대 결과도 쓴 사람이 실행하면 문제가 없었다. AI는 그 맥락이 없다. 빈칸을 그럴듯하게 채운다. 그리고 그럴듯하게 채운 기대 결과로 통과 를 판정한다. 모듈 18c 레슨 3의 "항상 통과하는 가짜 테스트"가 만들어지는 가장 흔한 경로가 바로 모호한 기준이다.
그래서 이 모듈의 첫 문장은 이것이다. AI의 판정은 기준보다 정확할 수 없다.
기준 한 줄의 다섯 칸
모듈 2 레슨 2에서 테스트 가능한 요구사항의 조건을 배웠다. 검증 기준은 그 조건을 판정 단위 로 쪼갠 것이다. 한 줄의 기준은 다섯 칸을 갖는다.
| 칸 | 질문 | 비었을 때 AI가 하는 일 |
|---|---|---|
| 대상 | 무엇을 검증하는가 (화면·API·필드·상태) | 비슷한 이름의 다른 대상을 검증한다 |
| 조건 | 어떤 전제·입력·상태에서 | 가장 쉬운 정상 경로 하나만 시험한다 |
| 관찰 | 무엇을 보고 판정하는가 (응답 코드·DB 값·화면 텍스트·로그) | 화면에 보이는 것만 본다 |
| 판정 | 통과와 실패의 경계는 정확히 무엇인가 | "대체로 맞으면" 통과시킨다 |
| 근거 | 이 기준은 어디서 왔는가 (요구사항 ID·정책·표준) | 기준이 바뀌어도 추적할 수 없다 |
예를 들어 보자.
[나쁜 기준]
VM 생성 시 적절한 오류 처리가 되어야 한다.
[다섯 칸을 채운 기준]
대상: POST /v1/projects/{id}/servers
조건: 프로젝트 GPU 쿼터가 이미 소진된 상태에서 GPU 플레이버로 생성 요청
관찰: HTTP 응답, 응답 본문의 error.code, 생성 요청 후 60초 동안의 서버 목록
판정: 통과 = 409 이고 error.code 가 QUOTA_EXCEEDED 이며, 서버 목록에 새 항목이 생기지 않음
실패 = 그 밖의 모든 경우 (202 후 ERROR 상태로 남는 경우 포함)
근거: REQ-COMPUTE-114, 쿼터 정책 문서 v3 §2"적절한 오류 처리"에서 사람은 409를 떠올린다. AI 에이전트는 400도, 500도, 심지어 202 후 ERROR 상태 도 "오류가 처리됐다"로 읽을 수 있다. 마지막 경우가 실제 운영에서 가장 비싼 결함이다 — 사용자 화면에는 성공이 뜨고, 리소스는 반쯤 만들어진 채 남는다.
판정의 두 종류 — 결정적 판정과 해석 판정
모든 기준을 LLM이 판정하게 두면 안 된다. 기준은 판정 방식에 따라 두 종류로 나뉜다.
| 종류 | 판정자 | 예 | 성질 |
|---|---|---|---|
| 결정적 판정 | 코드(어서션·스키마 검사·쿼리) | 응답 코드 409, JSON 스키마 일치, DB 행 수 0 | 같은 입력에 항상 같은 결과. 싸고 빠르다 |
| 해석 판정 | LLM 판정자(또는 사람) | 오류 메시지가 사용자가 다음 행동을 알 수 있게 쓰였는가, 로그 요약이 원인을 정확히 짚는가 | 판정이 흔들릴 수 있다. 보정이 필요하다(레슨 3) |
원칙은 단순하다. 결정적으로 판정할 수 있는 것은 반드시 결정적으로 판정한다. LLM은 코드로 판정할 수 없는 것에만 쓴다. Anthropic이 2026년 1월 공개한 에이전트 평가 가이드도 판정자(grader)를 코드 판정자·모델 판정자·사람 판정자로 나누고, 이들을 섞어 쓰되 사람의 보정을 곁들이라고 권한다.
이 구분은 기준을 쓰는 단계에서 이미 정해져야 한다. 기준 문서에 판정 방식 칸을 하나 더 두는 조직이 많다.
판정 방식: 결정적 (assert status == 409 and body.error.code == "QUOTA_EXCEEDED")
판정 방식: 해석 (루브릭 R-ERRMSG-02, 판정자 보정 기록 2026-09-01 kappa 0.78)해석 판정 기준에는 루브릭 이 붙는다. 루브릭은 판정자에게 주는 채점표다.
[루브릭 R-ERRMSG-02 — 오류 메시지의 행동 가능성]
PASS 메시지가 (1) 무엇이 실패했는지 (2) 왜 실패했는지 (3) 사용자가 할 수 있는 다음 행동
세 가지를 모두 포함한다.
FAIL 세 가지 중 하나라도 빠지거나, 내부 코드·스택 트레이스가 사용자에게 노출된다.
판정 근거로 메시지에서 세 요소에 해당하는 구절을 인용한다. 인용할 수 없으면 FAIL.
예시 PASS: "GPU 쿼터(8개)를 모두 사용해 서버를 만들 수 없습니다. 사용하지 않는 서버를
삭제하거나 관리자에게 쿼터 증설을 요청하세요."
예시 FAIL: "요청을 처리할 수 없습니다." (이유·다음 행동 없음)루브릭에서 가장 중요한 줄은 마지막이다. 판정 근거로 인용을 요구하고, 인용할 수 없으면 실패로 둔다. 판정자가 근거 없이 통과를 내는 경로를 구조적으로 막는다. 이 인용이 레슨 5에서 배포 판정의 근거 기록 이 된다.
요구사항에서 기준 뽑기
요구사항 문서는 기준의 1차 원천이다. 모듈 2 레슨 4의 수용 기준(Acceptance Criteria)이 이미 있다면 출발점으로 쓴다. 다만 수용 기준은 대개 사람이 합의하기 위한 문장 이라 판정 단위로 한 번 더 쪼개야 한다.
[수용 기준]
Given 사용자가 GPU 쿼터를 초과한 상태에서
When GPU 인스턴스 생성을 요청하면
Then 생성이 거부되고 쿼터 초과 안내를 받는다
[쪼갠 검증 기준]
C-1 (결정적) API 응답 409, error.code = QUOTA_EXCEEDED
C-2 (결정적) 요청 후 60초 동안 서버 목록·볼륨 목록·포트 목록에 새 리소스 없음 ← 부분 생성 누수
C-3 (결정적) 프로젝트 사용량 카운터가 요청 전과 동일 ← 쿼터 카운터 오염
C-4 (결정적) 감사 로그에 거부 이벤트 1건, actor·project·flavor 기록
C-5 (해석) 콘솔에 표시되는 메시지가 루브릭 R-ERRMSG-02 충족"생성이 거부된다"는 한 문장이 C-1~C-3 세 기준으로 쪼개졌다. 인프라 플랫폼에서 거부 는 응답 하나로 끝나지 않는다. 비동기로 만들어지던 볼륨·포트가 남는지, 사용량 카운터가 먼저 올라갔다가 안 내려오는지까지 봐야 거부가 "깨끗하게" 된 것이다. 이런 부수 효과 기준은 요구사항 문서에 거의 적혀 있지 않다. 도메인을 아는 QA가 채워 넣는 칸 이고, 이 모듈에서 QA의 전문성이 가장 크게 드러나는 곳이다.
화면에서 기준 뽑기
화면 기준은 AI가 가장 쉽게 "대충 통과"시키는 영역이다. 스크린샷을 보고 "정상적으로 보인다"고 판정하기 때문이다. 화면 기준은 세 층으로 나눠 쓴다.
| 층 | 기준 예 | 판정 방식 |
|---|---|---|
| 구조 | 생성 폼에 이름·플레이버·이미지·네트워크 필드가 있고, 필수 필드 미입력 시 제출 버튼 비활성 | 결정적 (접근성 트리·로케이터) |
| 상태 반영 | 생성 요청 후 목록의 상태 배지가 BUILD → ACTIVE 로 바뀌고, 새로고침 없이 반영 | 결정적 (API 상태와 화면 텍스트 대조) |
| 의미 | 쿼터가 80% 이상일 때 경고가 사용자가 알아볼 수 있는 위치·문구로 표시 | 해석 (루브릭 + 스크린샷) |
핵심은 상태 반영 층이다. 화면 기준을 화면 안에서만 판정하지 말고, 같은 시점의 API나 DB 값과 대조 해서 판정한다. 화면에 ACTIVE가 떠 있어도 API는 ERROR일 수 있다. Playwright MCP 같은 도구로 에이전트가 화면을 조작하게 할 때(모듈 18a 레슨 7), 판정은 화면 대 원천 대조로 설계해야 스크린샷 "느낌"으로 통과하는 일을 막는다.
API에서 기준 뽑기
API는 기준을 가장 기계적으로 뽑을 수 있는 원천이다. OpenAPI 명세가 있으면(모듈 12 레슨 4) 명세 자체가 결정적 기준의 목록이다.
명세에서 자동으로 나오는 기준
- 경로·메서드별 허용 응답 코드 집합 (명세에 없는 코드가 오면 실패)
- 응답 스키마 (필수 필드·타입·enum)
- 요청 스키마 경계 (minLength·maximum·pattern) → 경계값 케이스
명세에 없어서 QA가 더해야 하는 기준
- 멱등성: 같은 Idempotency-Key 로 두 번 요청 시 리소스 1개
- 권한: 다른 프로젝트 토큰으로 요청 시 404(존재 은닉) 또는 403 — 정책 확인 필요
- 비동기 상태 수렴: 202 응답 후 N초 안에 최종 상태 도달, 중간 상태 목록
- 부수 효과: 쿼터·과금 이벤트·감사 로그AI에게 "이 API를 테스트하라"고 하면 명세에서 나오는 기준은 잘 펼친다. 명세 밖 기준은 거의 펼치지 않는다. 그러니 QA가 쓰는 기준 문서는 명세 밖 기준 에 집중하는 편이 효율적이다. 명세에서 나오는 것은 명세를 입력으로 주면 된다.
AI가 읽는 기준에서 새로 생기는 함정
기준을 사람이 아니라 AI가 읽으면 세 가지 새 함정이 생긴다.
형용사 함정. "빠르게", "적절히", "정상적으로"는 AI가 가장 관대하게 해석하는 단어다. 수치나 관찰 가능한 사실로 바꾼다. "빠르게"는 "p95 800ms 이하, 측정 조건: 동시 50요청"이다.
부정 기준 누락. 사람은 "생성된다"를 쓰면 "엉뚱한 것은 생성되지 않는다"를 당연히 안다. AI는 명시되지 않은 부정 조건을 시험하지 않는다. 위 C-2·C-3처럼 일어나지 않아야 할 일 을 기준으로 따로 쓴다.
기대 결과를 구현에서 가져오기. 에이전트는 기준이 모호하면 코드를 읽고 "현재 동작"을 기대 결과로 삼는다. 이렇게 만든 테스트는 결함을 영원히 통과시킨다. 기준 문서에 근거 칸을 강제하는 이유가 이것이다. 근거가 요구사항·정책·표준이 아니라 "현재 구현"이면 그 기준은 기준이 아니라 스냅샷이다.
실무에서 왜 필요한가
AI 검증을 도입한 팀에서 가장 먼저 터지는 문제는 "AI가 다 통과라고 했는데 운영에서 터졌다"이다. 원인을 추적하면 대개 AI의 능력이 아니라 기준의 빈칸 이다. 판정자가 틀린 것이 아니라 틀리게 판정해도 되는 기준을 받았다.
기준을 다섯 칸으로 쓰기 시작하면 세 가지가 달라진다. 첫째, AI가 펼친 케이스를 사람이 검토할 때 기준 대비 누락 을 볼 수 있다. 둘째, 판정이 틀렸을 때 기준 문제인지 판정자 문제인지 가를 수 있다(레슨 3). 셋째, 같은 기준을 PR·회귀·릴리스 게이트 어디서든 재사용할 수 있다(레슨 4). 케이스는 AI가 매번 새로 펼쳐도 기준은 자산으로 남는다.
채용 공고가 "케이스를 일일이 쓰는 대신 AI가 케이스로 펼쳐 검증·판정할 기준을 요구사항·화면·API에서 설계"라고 쓸 때 요구하는 것이 정확히 이 능력이다. 면접에서는 "어떤 기준을 썼는가"보다 "어떤 빈칸을 채워서 어떤 결함을 잡았는가" 가 설득력을 갖는다.