고민의 흔적

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

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

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

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

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

운영자가 수동 재실행 버튼을 누르는 순간, 개발자는 잠에서 깬다. 숫자가 어긋나면 기능 버그가 아니라 신뢰가 무너진다.

걱정했던 시나리오 (이유)

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

하나만 터져도 숫자가 어긋나면 신뢰가 바로 무너졌다. 결제/정산에서 배운 것처럼, ‘재시도 = 안전’이라는 착각이 가장 위험했다.

설계할 때의 갈림길 — 왜 이쪽을 택했는가

1. DB 유니크 키로 막기

단순하고 강했지만, 예외 처리가 지저분해질 수 있었다. 중복 INSERT가 예외로 터지면, 그게 ‘정상적인 중복 차단’인지 ‘진짜 오류’인지 코드에서 구분해야 했다. 새벽에 로그만 보면 둘 다 똑같이 빨간색이다.

2. 상태 테이블로 흡수하기

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

3. 업무 키 + 처리 이력 (당시 결론)

구현은 무거웠지만, 운영 설명이 쉬웠다. ‘이 업무 키는 이미 처리됨’이라고 운영자에게 한 문장으로 말할 수 있었다. 장애 새벽에 설명 가능한 것이 코드 아름다움보다 중요했다.

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

PG 매입 배치에는 업무 키 + 처리 이력 방식을 택했다. 유니크 키는 최후의 안전망으로만 깔았다. 논리(이력 체크) + 물리(유니크 제약) 두 겹으로 막았다.

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

발송 API가 타임아웃 났을 때, 실제로는 ‘발송 성공 + 응답만 유실’인 경우가 있었다.

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

지금 생각과 개선점

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

  • 멱등 처리 이력이 쌓이기만 하고, 보관 주기·아카이빙 정책이 명확하지 않다.
  • ‘이미 처리됨’으로 건너뛴 건을 운영자가 사후에 확인할 화면이 부족하다.
  • 부분 성공 후 재시작 시, 어디까지 처리됐는지 보여주는 재처리 가시성이 약하다.

앞으로 나가야 할 방향

  1. 처리 이력에 보관 주기·파티셔닝을 적용한다.
  2. ‘스킵된 건/재처리된 건’ 모니터링 화면을 붙인다.
  3. 재실행 시나리오를 자동 테스트로 박제한다.
  4. 결제/정산 체크리스트와 묶어 공통 설계 원칙으로 정리한다.

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

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