개념
이 레슨의 경계 — 한 건의 메시지에서 한 묶음의 패턴으로
실패 자동 분류는 이 커리큘럼에 이미 두 번 나왔고, 둘 다 실패 한 건 안에서 얻는 신호 를 썼다.
| 다루는 범위 | 쓰는 신호 | |
|---|---|---|
| m13 레슨 10 | 테스트 프레임워크의 커스텀 리포터 | 실패한 단계(fixture / UI / cleanup)와 오류 메시지 패턴 |
| m18a 레슨 15 | 셀프힐링 래퍼의 판정 | 대체 후보 수와 신뢰도 — 모호하면 치유하지 않고 결함 후보로 |
| m59 레슨 7 — 이 레슨 | 실행 플랫폼의 분류 엔진 | 여러 테스트·여러 실행에 걸친 패턴 + 설비·환경 상태 + 이력 |
차이를 한 문장으로 쓰면 이렇다. m13 은 "이 실패의 메시지가 무엇을 말하는가"를 묻고, 이 레슨은 "이 실패가 다른 실패들과 함께 무엇을 말하는가" 를 묻는다.
왜 한 단계 올려야 하는지는 예로 보면 분명하다. 메시지만 보면 로케이터 타임아웃인 실패가 300건 동시에 났다. m13 의 규칙은 300건을 모두 "셀렉터 오류"로 분류하고 자동화 담당에게 보낸다. 담당자는 20분을 쓰고 나서야 실제 원인이 "스테이징 애플리케이션이 기동 중이어서 모든 화면이 로딩 스피너였다"는 것을 발견한다. 동시 실패 300건이라는 사실 자체가 가장 강한 신호 였는데, 실패 한 건의 시야에서는 그 신호가 보이지 않는다.
세 범주와 각 범주가 가는 곳
분류 라벨은 세 개로 충분하고, 네 번째는 unknown 이다. 범주를 늘리면 규칙이
복잡해지고 정확도가 떨어진다.
| 라벨 | 뜻 | 받는 사람 | 이어지는 조치 |
|---|---|---|---|
product-defect | 제품이 기대와 다르게 동작한다 | 개발팀 | 결함 초안 생성 → 사람 확인 후 등록 |
env-issue | 테스트 환경·설비가 정상이 아니다 | TestOps 당번 / 플랫폼 | 결함 등록하지 않음, 환경 복구 후 재실행, 집계 제외 표시 |
test-defect | 테스트 쪽이 틀렸다(기대값·셀렉터·대기·데이터 가정) | 자동화 담당 / 테스트 소유자 | 테스트 수정 또는 플래키 장부 등록(레슨 4) |
unknown | 신호가 모순되거나 부족하다 | 당번이 직접 본다 | 분류 후 규칙 개선 후보로 기록 |
범주별로 결함 등록 정책이 다르다 는 점이 중요하다. env-issue 를 결함으로 등록하면
결함 추세가 오염되고, product-defect 를 자동 등록하면 오탐이 그대로 결함 데이터에
들어간다. 자동 분류의 결과는 라우팅에 쓰고, 등록은 사람이 한다.
분류 신호 — 플랫폼만 볼 수 있는 것들
실행 플랫폼은 테스트 한 건보다 많은 것을 안다. 다섯 종류의 신호를 조합한다.
① 블라스트 반경(동시 실패 규모와 분포). 한 실행에서 실패한 테스트의 비율과 분포가 가장 강한 신호다.
동시 실패 비율과 분포로 보는 1차 판정
실패 비율 30% 이상, 여러 기능 영역에 고르게 퍼짐
→ env-issue 강한 후보 (환경·설비·공용 데이터)
실패가 한 기능 영역(예: 결제)에 몰림
→ product-defect 또는 그 영역의 테스트 결함
실패 1~2건, 산발적, 과거에도 갈린 이력 있음
→ test-defect / 플래키 (레슨 4의 장부 확인)
실패 비율 100%, 첫 테스트부터 전부
→ env-issue 거의 확정 (프리플라이트가 놓친 경우)② 환경 헬스체크 결과. 레슨 3의 프리플라이트와, 실행 중 주기적으로 찍는 헬스
스냅샷을 쓴다. 실패 시각과 의존 서비스 비정상 구간이 겹치면 env-issue 가 거의
확정된다. 이 신호가 있으면 오류 메시지를 읽을 필요가 없어진다.
③ 환경 좌표 변화. 직전 성공 실행과 이번 실패 실행의 좌표(레슨 3)를 비교한다. 스키마 head 가 바뀌었다면 마이그레이션 관련, 시드 세트가 바뀌었다면 기준 데이터 관련, 플래그가 바뀌었다면 구성 관련 — 각각 다른 담당에게 간다. 좌표가 동일한데 결과가 갈렸다면 그건 정의상 플래키다.
④ 최초 실패 커밋. 같은 테스트의 이력에서 통과→실패로 바뀐 경계 커밋을 찾는다.
경계 커밋이 제품 코드만 건드렸다면 product-defect 후보, 테스트 코드만 건드렸다면
test-defect 후보다. 둘 다 건드렸으면 unknown 으로 두고 사람에게 넘긴다. 이
신호는 레슨 6의 커밋-결과 연계가 있어야 계산할 수 있다.
⑤ 설비 신호. 러너의 CPU·메모리 포화, 그리드 세션 대기 급증, 디스크 부족, 단말
설치 실패(레슨 2). 이 신호가 있으면 타임아웃 계열 실패는 env-issue 로 보내야 한다.
설비 포화 상태의 타임아웃을 test-defect 로 보내는 것이 실무에서 가장 흔한 오분류다.
여기에 m13 레슨 10의 단계·메시지 신호 를 6번째로 더한다. 플랫폼 차원의 신호가 모두 중립일 때 마지막으로 보는 것이 메시지다 — 순서가 거꾸로 되면 위의 300건 사례가 반복된다.
규칙의 순서 — 넓은 신호부터 좁은 신호로
분류 규칙은 평가 순서가 결과를 결정한다. 범위가 넓은 신호를 먼저 본다.
트리아지 규칙 (평가 순서대로)
R1. 프리플라이트 실패 또는 실행 중 의존 서비스 비정상 구간과 겹침
→ env-issue (신뢰도 높음). 결함 등록 금지, 집계 제외, 당번 알림.
R2. 실행 전체 실패 비율이 30% 이상이고 여러 기능 영역에 분산
→ env-issue (신뢰도 중간). 당번이 환경 확인 후 확정하거나 R6 로 내린다.
R3. 설비 포화 신호(러너 자원·세션 대기·디스크) 가 실패 시각과 겹침
→ env-issue (신뢰도 중간). 실패 유형이 타임아웃 계열일 때만 적용.
R4. 해당 테스트가 플래키 장부에 '관찰중' 또는 '격리' 상태
→ test-defect / 플래키로 라우팅. 게이트 차단하지 않음(레슨 4).
R5. 최초 실패 커밋이 식별되고 그 커밋이 한쪽만 변경
제품 코드만 → product-defect 후보 / 테스트 코드만 → test-defect 후보
R6. 위가 모두 중립이면 단계·메시지 신호(m13 레슨 10의 분류기)를 적용
fixture 단계 실패 → env-issue
로케이터 타임아웃·strict 위반 → test-defect 후보
단언 실패 → product-defect 후보
R7. 신호가 서로 모순되거나 R1~R6 중 어느 것도 걸리지 않음
→ unknown. 당번 큐로 보내고, 사람의 최종 분류를 규칙 개선 입력으로 기록한다.R6 이 마지막에 오는 것이 이 레슨의 핵심이다. 메시지는 가장 구체적이지만 가장 좁은 증거이고, 좁은 증거를 먼저 보면 넓은 원인을 놓친다.
규칙마다 신뢰도를 명시 하는 것도 중요하다. 신뢰도가 높은 규칙(R1)은 자동으로 확정하고, 중간인 규칙(R2·R3)은 라우팅만 하고 확정은 사람이 한다. 모든 규칙을 확정으로 다루면 오분류가 조용히 쌓인다.
오분류의 대가 — 방향마다 비용이 다르다
자동 분류의 설계는 정확도 최적화가 아니라 비용 비대칭 설계 다. 오분류 여섯 방향의 비용이 전부 다르다.
| 실제 → 분류 | 무슨 일이 벌어지는가 | 비용 |
|---|---|---|
| 제품 결함 → 환경 문제 | 결함이 등록되지 않고 재실행 대상이 된다. 환경 복구 후에도 실패하면 발견되지만, 그 사이 배포가 나갈 수 있다 | 가장 크다 — 결함 유출 |
| 제품 결함 → 테스트 결함 | 자동화 담당이 테스트를 "고치려" 하다가 기대값을 제품에 맞춰 바꾼다. 결함이 영구히 숨는다 | 매우 크다 — 은폐 |
| 환경 문제 → 제품 결함 | 개발팀에 오탐 결함이 간다. 신뢰가 깎이고, 반복되면 자동화 결함을 전부 무시하게 된다 | 중간 — 신뢰 손실 |
| 환경 문제 → 테스트 결함 | 자동화 담당이 멀쩡한 테스트를 들여다본다. 시간 낭비 | 작다 |
| 테스트 결함 → 제품 결함 | 개발팀이 조사하고 "제품 정상"으로 반송한다. 왕복 비용 | 중간 |
| 테스트 결함 → 환경 문제 | 재실행하고 또 실패한다. 플래키로 쌓이고 원인이 안 밝혀진다 | 중간 |
첫 두 줄이 나머지보다 훨씬 비싸다. 여기서 설계 원칙이 나온다.
의심스러우면
product-defect쪽으로 기울인다. 오탐 결함의 비용(개발팀의 조사 시간)은 결함 유출의 비용보다 작다.
구체적으로는 두 가지 장치가 된다. 첫째, 단언 실패는 다른 신호가 명확히 반대하지
않는 한 product-defect 후보로 둔다. 둘째, env-issue 로 분류한 건은 환경 복구
후 반드시 재실행하고, 재실행에서도 실패하면 자동으로 product-defect 후보로
승격한다. 이 승격 규칙이 없으면 env-issue 가 결함의 무덤이 된다 — 레슨 4의 격리가
쓰레기통이 되는 것과 같은 구조다.
env-issue 승격 규칙
1. env-issue 로 분류 → 환경 복구 후 24시간 안에 같은 좌표에서 재실행
2. 재실행 통과 → env-issue 확정, 종결
3. 재실행 실패 → 라벨을 unknown 으로 올리고 당번 큐로. 자동 종결 금지
4. 재실행이 24시간 안에 일어나지 않음 → 당번 큐로 (방치 방지)사람에게 넘기는 기준
자동 분류의 목표는 100%가 아니다. 목표는 사람이 봐야 하는 건수를 감당 가능한 수준으로 줄이는 것 이고, 어디까지 자동으로 할지는 명시적으로 정한다.
사람에게 넘기는 조건 (하나라도 해당하면 당번 큐)
- 라벨이 unknown
- 신뢰도 '중간' 규칙으로 분류되었고, 라벨이 env-issue 이며 블라스트 반경이 50% 이상
(대량 실패를 자동 종결하지 않는다)
- product-defect 후보 — 결함 등록은 항상 사람이 한다
- env-issue 재실행에서 또 실패
- 동일 테스트가 7일 안에 서로 다른 라벨로 3회 이상 분류됨 (규칙이 흔들린다는 신호)
- 릴리스 판정 대상 실행(레슨 6의 증거에 들어가는 실행)의 모든 실패마지막 줄이 실용적으로 중요하다. 평상시 실행은 자동 분류에 맡기되, 릴리스 증거가 되는 실행은 전수 사람 확인 을 거친다. 판정에 쓰이는 데이터의 품질 기준을 평상시보다 높게 두는 것이다.
분류기 자체를 운영한다
분류 규칙은 만들고 끝나는 코드가 아니다. 세 가지가 필요하다.
① 분류기의 회귀 시험. 각 라벨을 일부러 만드는 샘플 실패를 고정해 두고, 규칙을
바꿀 때마다 그 샘플들이 기대 라벨로 분류되는지 확인한다. m13 레슨 10이 지적한
"메시지 형식 의존" 문제가 플랫폼 차원에서도 그대로 적용된다 — 도구 버전을 올리면
메시지가 바뀌고, 바뀐 메시지는 조용히 unknown 을 늘린다.
② 정확도 측정. 사람이 최종 분류한 결과를 정답으로 두고, 자동 라벨과 비교한다. 전체 정확도 하나가 아니라 방향별 오분류 건수 를 본다 — 비용이 다르기 때문이다. "제품 결함을 환경 문제로 보낸 건수"는 0 을 목표로 두고, 나머지는 추세만 본다.
③ unknown 비율 추세. 이 비율이 올라가면 규칙이 현실과 멀어지고 있다는 신호다.
레슨 5의 지표 중 트리아지 소요 시간과 함께 보면, 분류 체계가 건강한지 한눈에 보인다.
분류기 건강 지표 (주간)
- unknown 비율 — 목표: 전체 실패의 15% 이하
- 방향별 오분류 — 제품→환경, 제품→테스트: 목표 0건
- 사람 재분류율 — 자동 라벨이 사람에 의해 뒤집힌 비율
- 트리아지 중위 소요 시간 (레슨 5의 ⑥)실무에서 왜 필요한가
트리아지는 TestOps 의 일 중 사람 시간을 가장 많이 먹는 항목이다. 실행당 실패 10건, 하루 8회 실행, 건당 분류 5분이면 하루 6시간 이상이 분류에만 든다. 이 시간은 테스트를 늘릴수록 선형으로 늘어나고, 어느 지점에서 자동화를 늘리지 못하게 만드는 상한 이 된다. 분류의 70%를 규칙으로 처리하면 그 상한이 세 배로 올라간다.
분류가 없을 때의 2차 효과가 더 크다. 분류되지 않은 실패는 "일단 재실행"으로 처리되고, 재실행으로 넘어간 실패는 추적되지 않는다. 그 상태가 몇 달 지나면 실패 데이터 전체가 무의미해지고, 레슨 5의 지표도 레슨 6의 증거도 믿을 수 없게 된다. 트리아지는 뒤의 모든 데이터의 품질을 결정하는 입구 다.
조직 관계에도 작용한다. 환경 문제를 결함으로 등록해 개발팀에 보내는 일이 반복되면, 개발팀은 QA 가 보내는 결함을 전부 의심하기 시작한다. 반대로 분류가 정확하면 개발팀에 가는 결함은 "조사할 가치가 있는 것"으로 신뢰받는다. 이 신뢰가 자동화가 실제로 품질에 기여하는지를 가른다.