고민의 흔적

이 블로그 고민의 흔적 카테고리 글

전체글 보기
#배치#멱등성#정산#데이터#설계

정산 배치, 멱등성을 어디까지 보장해야 할까

재처리와 중복 적재 사이에서 밤새 고민했던 배치 설계 이야기다.

PG 매입 배치를 붙이면서, 코드보다 먼저 머릿속에서 맴돌던 게 있었다.
이 배치를 두 번 돌리면 어떻게 되지?

걱정했던 시나리오

  • 네트워크 타임아웃 후 재시도
  • 운영자의 수동 재실행
  • 배치 스케줄 중복 실행
  • 부분 성공 후 재시작

하나만 터져도 숫자가 어긋나면 신뢰가 바로 무너졌다.

설계할 때의 갈림길 (이유)

  1. DB 유니크 키로 막기
    단순하고 강했지만, 예외 처리가 지저분해질 수 있었다. 중복 INSERT가 예외로 터지면, 그게 “정상적인 중복 차단”인지 “진짜 오류”인지 코드에서 구분해야 했다.

  2. 상태 테이블로 흡수하기
    추적은 쉬웠지만, 테이블이 늘어났다. 그리고 상태를 갱신하는 순간 자체가 또 멱등해야 하는, 책임이 한 단계 더 미뤄지는 구조였다.

  3. 업무 키 + 처리 이력으로 멱등 보장
    구현은 무거웠지만, 운영 설명이 쉬웠다. “이 업무 키는 이미 처리됨”이라고 운영자에게 한 문장으로 말할 수 있었다.

세 갈래 모두 장단이 분명했다. 결국 기준은 “가장 똑똑한 방법”이 아니라, 장애 새벽에 운영자가 이해하고 재실행할 수 있는 방법이었다.

당시 결론

PG 매입 배치에는 업무 키 + 처리 이력 방식을 택했다. 성능보다 “설명 가능성”을 우선했고, 유니크 키는 그 위에 최후의 안전망으로만 깔았다. 즉 한 가지에 전부 거는 대신, 논리(이력 체크) + 물리(유니크 제약) 두 겹으로 막았다.

비슷한 경험 — 알림톡 재발송

같은 고민이 알림톡/메일 발송에서도 반복됐다. 발송 API가 타임아웃 났을 때, 실제로는 “발송 성공 + 응답만 유실”인 경우가 있었다.

  • 이유: 그냥 재시도하면 고객이 같은 알림을 두 번 받았다. 결제 중복만큼 치명적이진 않아도, 신뢰를 깎는 건 똑같았다.
  • 당시 결론: 발송 요청 단위에 요청 키(주문번호+이벤트타입) 를 두고, 동일 키는 일정 시간 내 재발송을 막았다. “재시도 = 안전”이 아니라 “재시도 = 같은 키면 한 번만”이라는 규칙으로 바꾼 것이다.
  • 도메인은 달라도 결국 멱등성의 본질은 같았다. ‘무엇이 같은 일인지부터 정의하는 것’.

지금 생각과 개선점

멱등성은 “기능”이 아니라 운영 신뢰 장치에 가까웠다.
그래서 개발 초기에 테스트 케이스를 “정상 1건”만 두지 않고, 재실행 시나리오부터 적어두기로 했다.

다만 아직 부족한 부분이 있다.

  • 멱등 처리 이력이 쌓이기만 하고, 보관 주기·아카이빙 정책이 명확하지 않아 테이블이 비대해진다.
  • “이미 처리됨”으로 건너뛴 건을 운영자가 사후에 확인할 화면이 부족하다. 로그를 직접 뒤져야 한다.
  • 부분 성공 후 재시작 시, 어디까지 처리됐는지 보여주는 재처리 가시성이 약하다.

앞으로 나가야 할 방향

  1. 처리 이력에 보관 주기·파티셔닝을 적용해, 멱등성을 지키면서도 운영 비용이 무한정 늘지 않게 한다.
  2. “스킵된 건/재처리된 건”을 운영자가 볼 수 있는 모니터링 화면을 붙여, 멱등성이 사람에게도 설명되게 만든다.
  3. 재실행 시나리오를 문서가 아니라 자동 테스트로 박제해, 코드가 바뀌어도 멱등성이 회귀하지 않도록 한다.
  4. 결제·정산 운영 기준(결제/정산 체크리스트)과 묶어, 멱등성을 개별 배치의 트릭이 아닌 공통 설계 원칙으로 정리한다.

아직 완벽하진 않다.
하지만 “재시도 = 안전”이라는 착각은 덜 하게 됐고, 다음 목표는 그 안전을 눈에 보이게(관측 가능하게) 만드는 것이다.

#배치#멱등성#정산#데이터#설계