일기 slecs

은행 이체 알림 판정을 정규식 우선으로 전환해 응답 속도 개선

목차

은행 이체 알림에서 "이체 완료" 여부를 판정하는 핸들러들을 손봤음. 부산, 기업, 전북, 케이, 카카오 - 핸들러 5종 전부 동일한 패턴으로 정렬하는 작업이었는데, 변경 자체는 단순한데 이 판단에 이르기까지 맥락이 좀 있어서 남겨둔다.

왜 AI-first 구조가 처음 선택됐는가

기존 구조는 AI 분류기를 1차로 돌리고, 거기서 못 잡으면 정규식이 보조하는 방식이었음. 설계 당시 논리는 그럴듯했다. 은행마다 알림 문구가 다르고, 문구가 바뀔 수도 있고, 패턴을 일일이 손으로 관리하면 유지보수 부담이 생긴다는 우려가 있었음. AI에 맡기면 문구 변형에도 알아서 대응한다는 기대감.

근데 운영에 들어가고 나서 실측값이 그 전제를 뒤흔들었음.

  • AI 호출당 평균 응답 800ms~2s
  • 정규식 매칭은 1ms 미만
  • 실측해보니 알림 메시지의 95% 이상이 정해진 템플릿
  • 은행마다 문구는 다르지만, 한 은행 안에선 거의 고정

마지막 항목이 핵심이었음. "은행마다 다르다"는 건 맞는데, "한 은행이 수시로 문구를 바꾼다"는 전제는 실제로 성립하지 않았음. 은행 알림 시스템은 보수적으로 운영되고, 한 번 정해진 포맷은 오래 간다. 즉 AI를 먼저 부르는 건 95% 케이스에 대해 비싼 추론을 낭비하는 구조였음.

AI 비용도 비용이지만 응답 지연이 사용자 체감에 그대로 꽂히는 게 더 직접적인 문제였다.

뒤집은 방법

구조 자체는 단순하게 순서만 바꿨음.

# 변경 전
메시지 → AI 분류 → (실패 시) 정규식 매칭

# 변경 후
메시지 → 정규식 매칭 → (미매칭 시) AI 폴백 → 결과 캐싱

판정 결과 자체는 동일하게 유지하는 게 전제였고, 핸들러별 인터페이스 계약도 그대로 둔 채 내부 호출 순서만 뒤집었음. 5종 핸들러가 다 같은 패턴을 공유하도록 정렬하는 게 이번 작업의 대부분.

구현하면서 몇 가지 신경 쓴 부분:

항목 처리 방식
정규식 미스 시 동작 기존 AI 경로로 그대로 폴백, 결과 캐싱
신규 문구 패턴 등장 AI 폴백 통계 모니터링 → 정규식 추가
핸들러별 정규식 충돌 가능성 핸들러가 은행 단위로 분리돼 있어 영향 없음
기존 테스트 AI-first 기준 테스트 케이스를 regex-first로 재실행, 동일 결과 확인

특히 "AI 폴백 호출 빈도"를 별도 메트릭으로 뺀 게 핵심이었음. 새로운 알림 템플릿이 등장하면 폴백 호출 수치가 튀고, 그 신호를 보고 정규식을 보강하는 피드백 루프가 생김. AI가 1차 판정자에서 패턴 발견 도구로 역할이 바뀐 셈.

폴백 없이 정규식만 단독으로 쓰는 방법도 고려했는데, 그렇게 하면 예외 케이스가 조용히 떨어져나가는 문제가 생김. AI 폴백을 유지하되 그것이 얼마나 자주 호출되는지 눈에 보이게 두는 게 더 낫다고 판단했음.

이 패턴이 의미하는 것

정규식 우선 / AI 폴백 구조는 "비용 최적화" 얘기로만 들릴 수 있는데, 실제로는 예측 가능성과 관찰 가능성에 대한 선택이기도 함.

정규식은 결과가 결정론적이다. 어떤 입력에 대해 매칭될지 안 될지 코드를 보면 알 수 있음. AI는 블랙박스 쪽에 가까워서, 왜 이 메시지를 이체 완료로 분류했는지 추적하기 어렵다. 버그가 생겼을 때 재현도 어렵고.

정형 데이터에 정규식을 쓰는 건 당연한 얘기처럼 들리는데, 비용·지연·정확도 세 지표를 동시에 실측하기 전엔 그 당연함이 잘 안 보임. 데이터가 생기고 나서야 "아 이게 맞는 구조였구나"가 분명해지는 것들이 있음.

반대로, AI-first로 시작했기 때문에 얻은 것도 있었음. 실제로 어떤 문구들이 들어오는지 데이터가 쌓였고, 95%가 템플릿이라는 확신이 생겼음. 그 확신 없이는 구조를 뒤집을 근거가 없었을 거임. 처음부터 정규식 1차로 갔다면 좋았을 것 같다는 생각도 들지만, 지금 시점에서 그렇게 말할 수 있는 게 운영 데이터가 있어서임을 감안하면 복잡한 심정이긴 하다.

어쨌든 이번 작업으로 5종 핸들러가 일관된 구조를 갖게 됐고, AI 폴백이 감시망 역할을 겸하게 됐음. 당분간은 폴백 호출 빈도 추이를 지켜볼 예정.

댓글 0

첫 댓글 달아줘.