X-ray펀드 개발로그 · 4화
데이터 오염은 느슨한 계약 네 곳의 사슬이었다: 고치자 분석이 멈췄다
한 종목 분석에서 숫자가 뒤섞이고 회사가 다른 회사로 바뀌었다. 우연한 환각이 아니라 네 곳의 느슨한 계약이 이어진 사슬이었다. 고친 뒤 다시 돌리자 분석은 대부분 멈췄다. 그게 맞는 결과였다.
8월 말, AI 반도체 회사 세레브라스를 분석하다가 이상한 보고서가 나왔다. 438억 달러가 넘는 숫자가 “주가”로 적혀 있고, 시가총액은 200만 달러 남짓이었다. 베타는 2만을 넘었고, 하루에 385% 움직였다고 했다. 그리고 이 숫자들을 근거로 즉시 팔라는 결론을 냈다. 회사 이름도 틀렸다. 세레브라스가 아니라 전혀 다른 광학 부품 회사로 보고 있었다.
다행히 이 보고서는 공식 판단으로 올라가지 않았다. 수집 원본 단계에서 “검증 전”으로 격리돼 있었다. 하지만 어디서 이런 숫자가 나왔는지는 끝까지 따라가야 했다.
네 곳이 이어진 사슬
따라가 보니 하나의 버그가 아니었다. 네 곳의 느슨한 계약이 차례로 이어져 있었다.
첫째, 수집기가 한 칸을 같이 썼다. 구글 스프레드시트의 금융 함수로 시세를 가져오는 수집기가 있었다. 이 스크립트는 모든 조회를 같은 임시 셀 하나에 수식으로 적고, 1.5초 기다렸다 읽고, 지우는 식으로 돌았다. 잠금이 없었다. 주가, 시가총액, 거래량, 지수를 동시에 네 번 요청하자 서로의 값을 읽었다. 시가총액이 주가 자리에, 거래량이 시가총액 자리에, 나스닥 지수가 베타 자리에, 채권 ETF 가격이 변동성 지수 자리에 들어갔다.
둘째, 이름 없이 티커만 넘겼다. 요청에는 회사 이름이 선택 항목이었고, 실제로 비어 있었다. 공시 식별번호도 붙지 않았다. 받은 쪽 모델은 티커 네 글자만 보고 회사를 추측했고, 틀렸다.
셋째, “완료”가 전송만 확인했다. 수집기가 성공했다는 판정은 응답 코드가 정상이고, 파일이 생겼고, JSON으로 읽힌다는 것뿐이었다. 주가가 시가총액보다 클 수 없다는 식의 값 자체의 불변식은 보지 않았다.
넷째, 출처 목록이 몰렸다. 분석 렌즈마다 웹 조사를 하는데, 공통 검색 두 개의 결과가 상위 10개 출처를 다 채웠다. 그래서 모든 렌즈가 같은 2차 출처 10개만 보고 있었다. 게이트는 숫자가 든 문장만 검사해서, 숫자 없이 틀린 주장은 그대로 지나갔다.
그래서 결론은 이렇게 적었다. 무작위 환각이 아니라 구조적 연쇄다. 모델이 헛것을 본 게 아니라, 헛것을 보게 만든 입력을 우리가 넘겼다.
고치고 다시 돌렸다
문제의 수집기를 빼고 나머지 여섯 수집기로 다시 돌렸다. 이번에는 SEC 공시, 시장 데이터, 외부 금융 API 세 곳이 같은 법인명과 같은 공시 식별번호로 일치했다. 회사를 잘못 알아보는 일은 없었다. 뒤섞인 극단값도 사라졌다.
대신 분석이 거의 끝나지 않았다. 16분 남짓 돈 뒤, 분석 작업 18개 중 끝까지 완료된 것은 2개였다. 나머지는 실패하거나, 품질이 떨어졌다고 표시되거나, 입력이 더 필요하다고 멈췄다. 일일 보고, 완결성 관리자, 대표 검토 모두 판단을 보류하고 닫혔다. 렌즈 게이트는 숫자 주장 667개를 검사해 229개를 강등했다.
처음에는 이게 실패처럼 보였다. 다시 보니 이게 맞는 결과였다. 근거가 모자라면 멈추라고 만든 시스템이 정확히 멈춘 것이다. 틀린 확신보다 정직한 보류가 낫다.
이 사고로 시세 수집기는 은퇴시켰다. 고칠 순서도 적었다. 요청에 회사 이름과 공시 식별번호를 반드시 묶고, 수집 결과에 값의 불변식 검사를 넣고, 렌즈마다 1차 출처를 먼저 채우고, 문장 단위로 근거를 대조한다.
문지기를 세웠다
8월 29일부터 사흘 동안 게이트를 사람으로 세웠다. 직원 하나가 관문 하나를 맡는다.
- 염라: 출처와 사용 권한의 문지기. 등록되지 않은 수집원이나 사용 범위가 불분명한 자료를 통과시키지 않는다.
- 피타고라스: 재무적으로 의미 있는 기업 간 연결만 등재한다.
- 돈데기리: 시간 원장. 사건마다 날짜와 회계 기간을 정리하고, 어긋나면 막는다.
- 듀이: 회사 문서철을 봉인한다.
- 버리: 리스크를 여러 각도로 점검한다.
9월 1일에는 세 사람이 운영하는 근거감사실을 따로 만들었다. 주장의 의미와 출처를 묶는 사람, 수치 모순을 찾는 사람, 최종 인계만 판정하는 사람이다. 앞에서 누가 실패해도 감사는 건너뛰지 않고, 실패 원인을 산출물에 남긴다.
9월 5일에는 재무 쪽 오류를 한 번 더 정리했다. 최근 12개월 합산 수치를 정확한 기간에 묶고, 한번 봉인한 재무 정리 파일은 덮어쓰지 못하게 막았다. 고객사는 한 덩어리로 뭉치지 않고 각각 따로 기록하게 했고, 인용 파서도 고쳤다. 그리고 원칙을 하나 적었다.
종목 불일치·원문 변조·출처 없는 수치는 20% 예외로 수용하지 않는다.
대부분의 규칙은 어느 정도 예외를 허용해도 괜찮다. 하지만 이 셋은 한 번만 통과시켜도 보고서 전체를 믿을 수 없게 만든다.
배운 것
모델이 틀리면 먼저 입력을 의심해야 했다. 이번 사고의 원인은 전부 모델 바깥, 우리가 짠 배관에 있었다. “완료”의 정의가 전송에서 끝나면 값이 틀려도 파이프라인은 초록색이다. 완료를 내용으로 정의하자, 시스템은 훨씬 자주 멈췄고 그만큼 믿을 만해졌다.