개발 slecs

우체국 계좌 검증 오류와 잘못된 실패 메시지 개선

목차

우체국 계좌 검증, 왜 자꾸 터졌나

파트너 출금 요청 흐름에서 우체국 계좌만 유독 실패율이 높았음. 다른 은행은 깔끔하게 통과하는데 우체국 쪽만 검증 단계에서 5xx 가 떨어지거나, 응답을 받았는데도 내부 파싱에서 NPE 가 나는 경우가 잦았음.

원인을 추적해 보니 두 가지가 겹쳐 있었음.

  • 외부 검증 API 의 응답 스키마가 케이스별로 달랐음. 정상/실패/점검 시점마다 필드 구성이 다른데, 우리 쪽은 "정상" 한 가지만 가정하고 짠 코드.
  • 검증 서버 자체가 간헐적으로 5xx 를 뱉는데, 그걸 그대로 사용자에게 노출. 사용자는 "내 계좌가 잘못됐나?" 오해하고 CS 로 들어옴.

이번에 손본 부분

구분 변경 전 변경 후
응답 파싱 정상 스키마만 가정 케이스별 분기 + 누락 필드 방어
5xx 처리 그대로 throw "일시 점검" 메시지로 매핑
재시도 없음 1회 백오프 후 재요청
로깅 메시지만 요청·응답 본문 마스킹 후 적재

기존엔 한 검증 핸들러에 분기가 다 몰려있어서, 헬퍼로 쪼개고 결과를 enum 으로 강제했음. 호출부에서 분기 누락하면 컴파일이 막히도록.

val outcome = when {
  response == null            -> UPSTREAM_DOWN
  response.code in 500..599   -> UPSTREAM_DOWN
  body?.ok == true            -> VERIFIED
  body?.code in softFailCodes -> RETRYABLE
  else                        -> INVALID
}

사용자 메시지 정리

  • VERIFIED → 다음 단계 진행
  • INVALID → "예금주/계좌번호를 다시 확인" (구체 사유는 숨김, 피싱 우려)
  • RETRYABLE / UPSTREAM_DOWN → "잠시 후 다시 시도" + 내부 알림
  • 5xx 가 일정 횟수 누적되면 운영 채널로 자동 알림

기존엔 RETRYABLEINVALID 처럼 보여서, 멀쩡한 계좌인데 사용자가 자기 계좌가 잘못된 줄 알고 새 계좌를 등록하는 사고가 있었음. 지원팀에서 같은 패턴 문의가 반복되길래 이참에 한꺼번에 정리.

회고

  • 외부 API 는 "정상 케이스"만 보고 짜면 반드시 터진다. 점검/장애/타임아웃 케이스까지 enum 으로 뽑아두는 게 결국 싸게 먹힘.
  • 5xx 를 사용자 메시지로 그대로 흘리면 CS 비용으로 돌아옴. 업스트림 상태와 사용자 메시지는 레이어를 분리해야 했음.
  • 응답 본문 로깅은 처음부터 마스킹 정책을 정해두자. 운영 올라간 뒤 빼는 게 훨씬 귀찮음.
  • "특정 은행만 실패" 류 이슈는 십중팔구 우리 코드보다 그쪽 응답 변종이 원인. 의심 순서를 바꾸니 디버깅 시간이 절반으로 줄었음.

다음

댓글 0

첫 댓글 달아줘.