개발 slecs

쿠폰 발급/환불 흐름의 엣지케이스 두 건을 연달아 잡은 오후

목차

오늘 오후 한 시간, 기능 추가나 리팩터보다는 조용히 쌓여 있던 버그 두 건을 순서대로 처리했다. 공통 주제는 쿠폰 관련 흐름의 예외 처리 미비였다. 둘 다 "정상 케이스엔 문제없지만 특정 조건이 겹치면 터진다"는 유형이라, 재현 경로를 먼저 좁히는 데 시간을 더 쓴 작업들이었다.


먼저 잡은 건: 대량환불 화면의 AJAX 무한로딩

zlgoon-bulk-refund.jsp — 이름에서 짐작하듯 즐거운 쪽 대량환불 관리 화면이다. 증상은 세션이 만료된 상태에서 AJAX 요청을 보내면 응답을 받지 못한 채 로딩 인디케이터만 돌고 있는 것이었다.

원인을 파고들면 구조가 단순하다. 세션 만료 시 서버는 JSON 대신 로그인 페이지 HTML(혹은 302 리다이렉트)을 돌려보내는데, 기존 AJAX 핸들러가 이 케이스를 처리하지 않고 있었다. 성공/실패 콜백은 있지만, "인증 실패로 다른 형식의 응답이 온 경우"를 걸러내는 분기가 없으니 그냥 응답 대기 상태로 굳어버리는 것이다.

수정 방향은 크게 두 가지였다:

처리 포인트 내용
응답 인터셉트 HTTP 상태코드 또는 응답 body를 확인해 세션 만료 여부 판별
사용자 안내 무한 로딩 대신 세션 만료 메시지 노출 후 로그인 페이지로 유도

대량환불처럼 운영자가 직접 쓰는 관리 화면일수록 이런 UX 함정이 치명적이다. 데이터를 선택하고 버튼을 눌렀는데 화면이 그냥 멈춰 있으면 "처리가 됐나, 안 됐나"를 알 수 없어서 혼란이 생긴다. 빠르게 수정해서 올렸다.


바로 이어서: 발급 실패 코드 010110의 정체

다음 건은 클라이프스 연동 쪽이었다. 외부 쿠폰 provider 연동 클래스에서 ISSUE_REQ_SN — 발급 요청 일련번호 — 이 20자를 초과하는 경우 발급 자체가 실패(오류코드 010110) 로 떨어지는 문제였다.

이쪽은 무한로딩보다 원인이 더 명확했다. 외부 연동 규격에서 해당 필드의 최대 길이를 20자로 정의해 놨는데, 내부에서 생성되는 일련번호가 특정 조건에서 그걸 넘기도 한다는 것이다. 평소엔 발급이 잘 되다가 간헐적으로 실패 로그가 찍히는 이유가 여기에 있었다.

// 수정 전: 길이 검증 없이 그대로 전달
issueReqSn = generateReqSn(...);

// 수정 후: 20자 초과 시 잘라내거나 생성 규칙 자체를 재조정
issueReqSn = ensureMaxLength(generateReqSn(...), 20);

단순히 truncate 하는 것보다 생성 규칙을 손봐서 애초에 넘지 않도록 하는 게 더 안전하다. 유니크 보장이 같이 따라오는 문제이기 때문에, 길이만 자르면 중복 충돌 가능성이 생긴다. 그 지점까지 고려해서 처리했다.


두 건을 묶어 보면

  • 겉으로 드러나는 증상은 달랐지만 (무한 로딩 vs. 발급 실패), 둘 다 "정해진 범위를 벗어난 입력·상태를 방어하지 않은" 패턴이다.
  • 한쪽은 프론트엔드 AJAX 레이어, 다른 한쪽은 백엔드 연동 클래스였지만 수정 난이도는 비슷했다. 재현 경로를 특정하고 나면 픽스 자체는 단순하다.
  • 이런 버그들은 대부분 "처음엔 드물게 발생해서 넘어갔다가, 트래픽이나 데이터 규모가 늘면서 빈도가 올라오는" 경향이 있다. 지금 잡아두는 게 맞다.

짧은 시간이었지만 실 운영에서 사용자가 직접 체감하는 흐름 두 군데를 정리한 오후였다.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.