가계부가 만든 유령 지출 500만원: SMS 파서 오탐 해부기
카드 승인 문자와 앱 알림을 읽어 자동으로 기록하는 개인 가계부 앱을 만들어 쓰고 있습니다. 어느 날 월 지출 합계를 봤더니 감각보다 수백만 원이 컸습니다. 파고들어 보니 실제로 쓴 돈이 아니라, 파서가 "금액이 적힌 텍스트"를 전부 지출로 믿어버린 결과였습니다. 이 글은 유령 지출을 만든 오탐 4종의 해부와, 앱 재배포 없이 서버에서 파서 규칙을 고치는 구조로 문제를 끝낸 기록입니다.
1. 발단: 합계가 감각과 다르다
자동 가계부의 장점은 "안 적어도 쌓인다"이고, 단점은 "쌓인 걸 안 보게 된다"입니다. 오랜만에 월 합계를 확인하니 700만 원대 — 체감의 두 배였습니다. 건별 기록을 금액 내림차순으로 훑자 범인들이 바로 보였습니다.
2. 오탐 4종 해부
유형 1: 안내문 속 숫자 (가장 큰 유령)
"고객님이 가입하신 보험을 만기까지 유지하려면
내야 할 총 보험료를 알려드려요. 남은 보험료: 3,4XX,XXX원"
핀테크 앱의 보험 관리 광고 알림입니다. 결제가 아니라 "앞으로 낼 수도 있는 돈"인데, 파서는 "원"으로 끝나는 금액을 찾아 지출 340여만 원으로 기록했습니다. 단일 건으로 최대의 유령이었습니다.
유형 2: 청구 예정 안내 (이중집계)
"[카드사] 다음 결제일 카드대금 3XX,XXX원 안내"
이미 건별로 기록된 결제들의 합계 고지입니다. 이걸 다시 지출로 잡으면 같은 돈이 두 번 집계됩니다.
유형 3: 대금 자동이체 출금 알림 (또 이중집계)
"출금 2,7XX,XXX원 ○○카드 잔액 XXX원"
은행 계좌에서 지난달 카드대금이 빠져나갔다는 알림입니다. 지난달에 이미 건별로 기록된 지출의 "납부"라서 새 지출이 아닙니다. 카드사 이름이 본문에 있으니 파서는 카드 결제로 오인했고, 이런 게 카드 3장 분으로 세 건 있었습니다.
유형 4: 증권 뉴스의 목표가 (가장 황당한 유령)
"○○ 종목 리서치 — 목표가 156.80달러 상향"
증권 앱의 뉴스 알림 속 목표 주가를 해외 결제 금액으로 해석해 20만 원대 지출이 생겼습니다. 며칠 간격으로 다섯 건. 뉴스 알림이 지출을 만들고 있었습니다.
3. 원인: 파서가 낙관적이었다
네 유형의 공통 원인은 하나입니다. "금액이 있으면 거래"라는 낙관적 매칭. 실제 승인 문자에는 "승인", "결제완료" 같은 마커가 거의 항상 있는데, 초기 파서는 이 마커를 필수로 요구하지 않았습니다. 금액 패턴만 맞으면 통과시켰으니, 광고·고지·뉴스 속 숫자가 전부 지출이 된 겁니다.
4. 해결: 규칙을 데이터로 빼고, 서버에서 교정한다
파서 코드를 고쳐 앱을 재배포할 수도 있지만, 오탐은 앞으로도 계속 새 형태로 나타납니다. 스토어 심사를 매번 기다릴 수는 없죠. 그래서 규칙을 코드에서 분리했습니다.
- 서버 룰 파일: 차단 키워드(비결제 안내), 광고 키워드, 승인 마커, 취소 마커를 JSON으로 서버에 두고, 앱이 동기화 때마다 받아 기본 규칙 위에 덮어씁니다. 규칙 수정 = 서버 파일 수정. 재배포가 없습니다.
- 계층 규칙: "보험료" 같은 차단 키워드가 있어도 "승인/결제완료" 마커가 있으면 통과시킵니다. 진짜 보험료 결제는 살고, 보험 광고는 죽습니다. 이 예외 계층이 없으면 차단 키워드를 추가할 때마다 실결제를 죽일까 봐 겁내게 됩니다.
- 원격 정리 명령: 이미 쌓인 오탐은 서버 명령 큐로 원격 휴지통 처리(복구 가능)했습니다. 폰에서 하나하나 지울 필요가 없습니다.
이렇게 오탐 십수 건을 정리하자 월 지출이 700만 원대에서 실제에 가까운 300만 원대로 내려왔습니다. 이후 새 오탐 유형이 나타날 때마다 서버 룰 파일에 키워드 한 줄을 보태는 것으로 대응이 끝납니다.
5. 남은 진실: 청구액과 사용액은 원래 다르다
오탐을 다 잡아도 가계부의 "이번 달 사용액"과 카드사의 "청구 예정액"은 일치하지 않습니다. 할부 이월분, 문자가 오지 않는 자동납부, 연회비는 SMS 기반 가계부가 원천적으로 볼 수 없는 돈입니다. 이건 오탐이 아니라 데이터 소스의 한계라서, 고치는 대신 화면에 "SMS로 잡힌 신규 사용액 기준"이라는 안내 문구를 붙여 기대치를 조정했습니다. 못 잡는 것을 숨기는 것보다 못 잡는다고 말하는 쪽이 신뢰를 만듭니다.
6. 교훈
- 금액이 있는 텍스트 ≠ 거래. 파서는 낙관적으로 매칭하면 안 됩니다. 긍정 신호(승인 마커)를 요구하는 화이트리스트 접근이 기본이어야 합니다.
- 분류 규칙은 코드가 아니라 데이터다. 오탐은 소프트웨어 버그가 아니라 세상의 다양성 문제라 끝없이 새로 나타납니다. 규칙을 서버 데이터로 빼면 대응 주기가 "스토어 심사"에서 "파일 수정"으로 줄어듭니다.
- 예외 계층을 함께 설계하라. 차단 규칙만 있으면 규칙 추가가 무서워집니다. "차단하되 승인 마커가 있으면 통과" 같은 우선순위 계층이 규칙을 마음 놓고 추가하게 해줍니다.
- 못 보는 돈은 못 본다고 표시하라. 자동화의 신뢰는 정확도가 아니라 한계의 정직한 고지에서 나옵니다.
FAQ
Q. 애초에 은행 API를 쓰면 되지 않나요?
개인 가계부 수준에서 전 카드사·은행을 커버하는 공식 API 접근은 비용과 절차의 벽이 높습니다. SMS/알림 파싱은 모든 카드에 즉시 통하는 보편 인터페이스라는 장점이 있고, 대신 이 글 같은 오탐 관리가 유지비입니다.
Q. LLM으로 분류하면 오탐이 없어지지 않나요?
줄어들 수는 있지만 건당 비용·지연·프라이버시(금융 문자를 외부로 보내는 문제)가 생깁니다. 키워드 계층 규칙은 공짜고, 기기 안에서 끝나며, 오탐이 나와도 원인을 즉시 설명할 수 있습니다. 설명 가능성은 돈 문제에서 특히 중요합니다.
Q. 오탐인지 실결제인지 헷갈리는 경계 사례는요?
원문 전체를 기록에 보존하는 게 핵심입니다. 분류가 틀려도 원문이 있으면 사후 판정과 규칙 개선이 가능합니다. 파싱 결과만 남기고 원문을 버리는 순간 디버깅이 불가능해집니다.


