일주일 전부터 평가 기준선(B-6)이 재현되지 않았습니다. 같은 코드, 같은 입력, 같은 드라이버인데 95행 중 85행이 달랐습니다. 다섯 회차 만에 원인이 나왔고, 버전 관리 안에는 없었습니다.
무엇이었나
2026-09-08 오후 5시 48분에 uv sync 가 extra 없이 한 번 돌았습니다. 그때 aws·tracking extra 가 통째로 제거됐고, 그중 torchvision 이 있었습니다.
transformers 5.x 는 torchvision 이 설치돼 있느냐로 이미지 전처리기를 다르게 고릅니다. 있으면 텐서 경로, 없으면 ...ImageProcessorPil 입니다. 리사이즈가 갈리면 픽셀이 미세하게 달라지고, 그러면 누구를 분석 대상으로 고르는지는 안 바뀌는데 관절각이 흔들립니다. 축구 19편 중 2편은 등급 문자까지 바뀌었습니다.
되살려서 다시 돌리니 95행 × 40열 불일치 0 으로 기준선이 그대로 재현됐습니다.
어떻게 찾았나 — 기록이 아니라 흔적
「그때 무엇으로 돌렸는지」가 아무 데도 없었습니다. 답을 준 것은 site-packages 디렉터리의 mtime 이었습니다. 마지막으로 재현된 실행(09-08 11:16)과 깨진 실행(09-15) 사이에, 그 디렉터리가 정확히 한 번 움직였습니다.
🔴 그 증거를 쓰기 전에 자를 먼저 검사한 것이 이번에도 갈랐습니다. uv 는 캐시에서 하드링크로 설치해서 파일의 mtime 은 설치 시각이 아닙니다(캐시에 들어온 시각입니다). 디렉터리만 설치 시각을 뜻합니다. 파일을 보고 읽었으면 엉뚱한 날짜를 근거로 삼을 뻔했습니다.
배운 것
uv.lock 이 안 바뀌었다는 것은 「같은 환경」이 아닙니다. 잠금 파일은 무엇을 깔 수 있나이고, 결과를 정하는 것은 무엇이 깔려 있나입니다. 이 조사의 1회차가 「의존성 무변경」을 배제 근거로 썼는데, 그때 본 것이 잠금 파일이라 이 사건을 통과시켰습니다.
그리고 선택적 의존성이 조용히 판정 경로를 정할 수 있습니다. torchvision 은 우리 pyproject.toml 에 적혀 있지도 않습니다 — 시각화용으로만 쓰는 ultralytics 가 끌고 오던 것이라, 아무도 의존성으로 인식하지 않은 채 판정 결과가 거기 매달려 있었습니다.
이제 매 실행이 run_meta.json 에 설치된 패키지 전부(105개·3KB)와 전처리 경로를 적습니다. 무엇이 중요한지는 사고가 난 뒤에 알게 되므로, 고르지 않고 전부 적는 쪽으로 했습니다.
그래서 더 큰 것이 나왔습니다
평가는 torchvision 경로에서, EC2 서비스는 Pil 경로에서 돕니다 — 배포 스크립트가 uv sync --extra aws 만 치기 때문입니다. 같은 영상에 두 경로가 다른 등급을 냅니다. 어느 쪽이 더 정확한지는 정답이 없어 못 재지만, 제품과 평가가 같은 것을 재고 있지 않다는 것은 그 자체로 문제입니다.
둘을 어느 쪽으로 통일할지는 제품 출력이 바뀌는 결정이라 팀에 올렸습니다 — 미결 항목 49번. 기준선을 새로 선언하는 일은 그것이 정해진 뒤입니다.