개발 slecs

은행별 입금 감시 오류 분류와 멱등성으로 이중 처리 방지

목차

입금 감시 로직, 은행마다 다르게 터지는 게 문제였음

여러 은행 핸들러에서 입금 완료 감시 로직이 들쭉날쭉이라 정리한 회고. 같은 "입금 확인"인데 은행별로 응답 포맷, 타임아웃 패턴, 에러코드가 다 달라서 분기마다 한 번씩 장애가 났음.

무엇이 문제였나

기존 구조는 각 은행 핸들러가 자기 방식대로 예외를 던지고, 상위 스케줄러는 그걸 단순히 catch만 하고 있었음. 결과적으로 이런 문제가 누적됨.

  • 일시적 네트워크 오류와 진짜 거래 실패가 같은 예외 타입으로 묶여서 재시도 정책이 무너짐
  • 한 은행 응답이 늦어지면 전체 폴링 사이클이 밀리는 현상
  • 입금 직후 짧은 지연 동안 "미입금"으로 응답하는 케이스를 실패로 오인
  • 운영 로그에는 스택트레이스만 남고 어떤 거래인지 추적이 어려움

폴링 주기는 짧은데 멱등성 보장이 약해서, 같은 입금 건이 두 번 처리되는 사고도 한 번 있었음.

핸들러별로 분리한 에러 카테고리

네 개 핸들러를 모두 손대면서 가장 먼저 한 건 에러를 세 가지로 명확히 분류한 것.

카테고리 의미 후속 처리
RETRYABLE 네트워크/타임아웃/일시적 응답 지연 백오프 후 재폴링
PENDING 응답은 정상이나 입금 미확인 다음 사이클로 넘김
FATAL 계좌 불일치, 인증 실패, 한도 초과 즉시 중단 + 알림
응답수신  파싱  카테고리 판정
   ├─ RETRYABLE  백오프 
   ├─ PENDING    다음 
   └─ FATAL      알림 + 상태확정

은행별로 같은 문구가 다른 의미로 쓰이는 게 까다로웠음. 어떤 은행은 "처리중"이 PENDING이고, 다른 은행은 사실상 RETRYABLE에 가까웠음. 핸들러 안에 매핑 테이블을 두고 외부에는 통일된 enum만 노출.

멱등키와 추적 ID

같은 거래 두 번 처리되는 사고를 막기 위해 입금 감시 단계에서도 멱등키를 강제. 거래 식별자 + 은행코드 + 사이클 시각을 조합해 키를 만들고, 처리 직전에 캐시로 락을 걸었음. 락 TTL은 폴링 주기의 두 배로 잡아서 사이클이 겹쳐도 안전하게.

추적 ID는 핸들러 진입 시점에 발급해서 로그·알림·후속 정산 레코드에 모두 심었음. 장애 났을 때 ID 하나로 전 구간을 따라갈 수 있어야 새벽에 깨도 사람이 살 수 있음.

공통 날짜 필터 JSP

운영팀이 거래 조회할 때 화면마다 달력 위젯 동작이 미묘하게 달라서, 어제/오늘/이번주 같은 기본 프리셋과 시작-종료일 검증을 하나의 JSP 조각으로 통일. 화면별로 복붙됐던 자바스크립트 다섯 군데가 한 곳으로 모임.

  • 오늘이 시작일 기본값, 종료일은 시작일 이전 선택 불가
  • 최대 조회 범위(예: 90일) 초과 시 즉시 경고
  • 모바일에서 깨지던 input type=date 처리 일원화

배운 것

  • "입금 감시"처럼 외부 시스템에 의존하는 로직은 에러 분류가 곧 재시도 정책이라 분류부터 합의하고 코드 짜야 함
  • 멱등성은 결제 본 흐름뿐 아니라 감시·정산 같은 보조 흐름에도 똑같이 필요함
  • 운영 화면 공통화는 기능 추가보다 돌발 장애 줄이는 효과가 더 큼

다음

댓글 0

첫 댓글 달아줘.