분류 결과에 unknown 레인을 꼭 두는 이유, 조용한 오분류 막기
자동 분류가 틀리면 조용히 넘어가는 게 가장 무섭습니다. 플랜비 회비 처리 예시로 unknown 레인을 강제하는 이유와 구현 방법을 정리했어요.
자동 분류 코드에서 제일 무서운 결과는 틀린 답이 아니에요. 틀렸는데 아무도 모르는 답이에요. 입력이 어떤 규칙에도 안 맞았는데 기본값으로 떨어지면, 로그에는 성공이라고 찍히고 화면에는 멀쩡한 숫자가 보여요. 플랜비처럼 회비를 다루는 앱에서는 이게 특히 치명적이라, 처음부터 원칙 하나를 정해 두고 있어요. 분류 결과에는 반드시 unknown 레인이 있어야 한다는 거예요.
조용한 오분류가 생기는 자리
동호회 회비 입금 내역을 멤버별 납부 상태로 바꾸는 코드를 떠올려 볼게요. 입금 메모에 이름이 정확히 있으면 '납부'로, 금액이 모자라면 '부분 납부'로 나눠요. 그런데 메모가 '농구'라고만 적혀 있으면요? 분기 2개짜리 코드는 둘 중 하나로 억지로 밀어 넣거나 그냥 건너뛰어요. 직접 만들어 보니 후자가 더 흔했어요. 반복문 안에서 continue 한 줄이면 조용히 사라지거든요.
입력 100건 중 3건이 이렇게 빠지면 어떻게 될까요? 총무는 미납자가 3명 있다고 믿고 독촉 메시지를 보내요. 돈은 이미 들어와 있는데요. 코드는 한 번도 에러를 낸 적이 없어서 뭐가 잘못됐는지 찾기도 어려워요.
unknown을 결과 타입에 박아 두기
해결책은 단순해요. 분류 결과를 2종이 아니라 3종으로 고정하고, 세 번째를 unknown으로 둬요. 중요한 건 '넣어도 된다'가 아니라 '없으면 컴파일이 안 된다'는 쪽이에요.
type DuesResult =
| { kind: "paid"; memberId: string }
| { kind: "partial"; memberId: string; short: number }
| { kind: "unknown"; raw: string; reason: string };이렇게 해 두면 결과를 소비하는 쪽에서 switch로 분기할 때 unknown을 안 다루면 타입 검사가 막아요. 적용해 봤더니 기존 코드에서 그냥 건너뛰던 자리가 전부 드러났어요. 파일 1개를 고치는 데 10분 정도 걸렸는데, 그 10분이 총무가 나중에 장부를 뒤지는 시간보다 훨씬 쌌어요.
unknown에는 원본 입력과 이유를 꼭 같이 남겨요. '매칭 실패'라고만 적으면 사람이 봐도 뭘 고쳐야 할지 몰라요. '이름 후보 2명, 금액 불일치'처럼 적어야 다음 규칙을 만들 재료가 돼요.
사람이 보는 자리까지가 구현이에요
unknown으로 격리만 하고 끝내면 기본값으로 떨어지던 것과 별 차이가 없어요. 로그 파일에만 쌓이면 아무도 안 읽거든요. 테스트해 보면 알 수 있는데, unknown 건수가 화면에 보여야 비로소 사람이 움직여요. 플랜비라면 회비 화면에 '확인 필요 2건' 같은 줄 하나가 그 역할을 해요. 총무가 그 2건을 열어 멤버를 직접 지정하면 끝이에요.
- 결과 타입에 unknown 강제
- 원본과 이유를 함께 저장
- 건수를 화면에 노출
- 사람이 처리하면 규칙으로 승격
돌려 보니 생긴 부수 효과
돌려 보니 unknown 큐가 그대로 규칙 개선 목록이 됐어요. 같은 이유로 unknown이 5건 넘게 쌓이면 규칙이 하나 빠졌다는 신호예요. 그때 규칙을 추가하면 다음 달엔 그 유형이 자동으로 처리돼요. 반대로 unknown이 0건이면 의심부터 해요. 분류기가 너무 잘 맞는 게 아니라, 어딘가에서 다시 기본값으로 떨어지고 있을 가능성이 크거든요.
AI 분류를 붙일 때도 똑같아요. 모델이 확신 없이 뱉은 답을 그대로 쓰지 말고, 신뢰도가 기준 아래면 unknown으로 보내요. 라이프케어로그 플랜 시리즈를 만들 때 지키려는 기준도 같아요. 자동화는 틀려도 되지만, 틀린 걸 숨기면 안 되니까요.
관련 글
댓글
아직 댓글이 없어요. 첫 댓글을 남겨주세요.