ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 초록불은 정답이 아니었다
    AI Agent 2026. 8. 5. 21:00
    728x90
    반응형

    테스트가 전부 초록이었는데 숫자가 틀렸습니다.

    이 문장은 이상하게 들립니다.
    테스트가 초록이면 맞아야 하니까요.
    저도 그렇게 생각했습니다.
    적어도 그날 전까지는요.

    문제는 값이 비어 있거나 터진 게 아니었다는 점입니다.
    화면에는 숫자가 있었습니다.
    심지어 그럴듯했습니다.
    0도 아니고, null도 아니고, 에러도 아니었습니다.
    그래서 더 오래 속았습니다.

    틀린 값은 조용했습니다

    처음엔 단위 테스트를 봤습니다.

    입력 A를 넣으면 출력 B가 나오는지 확인하는 테스트였습니다.
    테스트는 통과했습니다.
    그래서 로직은 맞다고 생각했습니다.
    그런데 실제 데이터에서 사용자가 보는 값은 이상했습니다.

    이럴 때 가장 위험한 말이 있습니다.

    “테스트는 통과하는데요.”

    맞는 말입니다.
    하지만 그 말은 테스트가 정의한 세계 안에서만 맞습니다.
    픽스처가 이미 틀린 질문을 하고 있다면, 테스트의 초록불은 아무 것도 보장하지 않습니다.

    예를 들어 이런 식입니다.

    이번 주 평균 = selected_rows 평균
    

    테스트는 selected_rows를 잘 만들고 평균도 잘 냅니다.
    그런데 실제 제품에서 “이번 주”가 로컬 시간 기준이어야 하는데 UTC로 잘렸다면요.
    평균 계산은 맞고, 질문이 틀린 겁니다.

    제가 한동안 헷갈린 지점이 여기였습니다.
    계산 버그를 찾고 있었는데, 실제 문제는 집합 정의였습니다.

    독립 재계산을 하자 다른 화면이 보였습니다

    그다음부터는 파이프라인 출력만 보지 않았습니다.

    raw 행을 다시 긁어와서, 파이프라인을 거치지 않고 독립적으로 계산했습니다.
    같은 기간, 같은 사용자 집합, 같은 단위로 다시 계산했습니다.
    그리고 출력과 diff를 냈습니다.

    그때부터 버그가 보였습니다.

    어떤 값은 초 단위와 밀리초 단위가 섞여 있었습니다.
    어떤 값은 baseline이 없는데 delta처럼 보였습니다.
    어떤 값은 0이 아니라 “데이터 없음”이어야 했습니다.

    테스트는 계속 초록이었습니다.

    그러니까 테스트가 나빴다는 뜻은 아닙니다.
    테스트는 자기가 맡은 일을 했습니다.
    다만 제가 테스트에게 너무 큰 주장을 맡겼던 겁니다.

    제가 지금 나누는 세 가지 주장

    이후로 데이터 관련 작업을 볼 때 주장을 세 개로 나눕니다.

    주장 필요한 증거
    함수가 입력을 처리한다 단위 테스트
    API가 계약대로 응답한다 핸들러/통합 테스트
    값이 실제로 맞다 raw 데이터 독립 재계산

    셋은 비슷해 보여도 다릅니다.

    단위 테스트가 GREEN이면 함수가 기대한 입력을 처리했다는 뜻입니다.
    API 테스트가 GREEN이면 경로와 인증과 응답 형태가 맞을 가능성이 높습니다.
    하지만 “이 숫자가 현실을 제대로 세고 있다”는 주장은 raw에서 다시 세봐야 닫힙니다.

    특히 통계, 랭킹, 요약, 추천처럼 해석이 끼는 값은 더 그렇습니다.
    값이 존재하는 것과 값이 맞는 것은 다릅니다.

    null, 0, 그리고 의미 없는 0

    가장 오래 남은 습관은 0을 의심하는 겁니다.

    0은 세 가지일 수 있습니다.

    진짜 변화가 없어서 0.

    데이터가 없는데 예전 코드가 채워 넣은 0.

    비교 대상이 같아서 계산 자체가 의미 없는 0.

    화면에서는 전부 같은 0입니다.
    하지만 제품 의미는 완전히 다릅니다.
    이걸 구분하지 않으면 사용자는 “아무 변화 없음”으로 읽고, 시스템은 사실 “모름”을 말하고 있을 수 있습니다.

    이후로 저는 데이터 계약에 이 구분을 먼저 적습니다.

    null = 데이터 부족
    0 = 실제 변화 없음
    degenerate = 비교 자체가 무의미
    

    이름은 못생겨도 됩니다.
    중요한 건 소비자가 구분할 수 있어야 한다는 점입니다.

    그날 이후 테스트 초록불을 덜 미워하게 됐습니다.
    대신 더 작게 믿습니다.

    초록불은 “여기까지는 봤다”는 신호입니다.
    “정답이다”는 신호가 아닙니다.

    728x90
    반응형
Designed by Tistory.