매출 숫자를 확인하는 화면을 만들어 달라는 요청을 받았다. 우리 시스템의 집계와 결제 대행사의 정산 내역을 비교하는 화면인데 숫자가 다를 때 어떻게 하나가 이 일의 전부였다.
Table of contents
Open Table of contents
먼저 왜 다른지 세어 봤다
만들기 전에 MySQL 에서 실제로 얼마나 다른지 봤다. 우리 쪽은 SUM 과 GROUP BY 로 날짜별 합을 내고 대행사 쪽은 내려받은 정산 파일을 읽어 한 달치를 대조했다.
차이 나는 건이 여럿 나왔고 이유가 여러 가지였다.
시점 차이 우리는 결제 요청 시각, 그쪽은 승인 시각 — 자정 근처가 갈린다
취소 반영 시점 우리는 즉시, 그쪽은 정산 주기
수수료 우리는 총액, 그쪽은 수수료 뺀 금액
누락 진짜로 한쪽에만 있는 것
앞의 셋은 정상이고 넷째만 문제였다. DATE() 로 자르는 기준 시각이 서로 다르면 같은 건이 양쪽에서 다른 날에 들어간다.
정상 차이를 먼저 없앴다
화면에 그냥 두 숫자를 나란히 놓으면 매일 안 맞는다. 그러면 보는 사람이 며칠 만에 그 화면을 안 보게 된다.
그래서 정상 차이를 SUM 결과에 반영했다.
우리 집계
- 자정 경계 조정
- 취소 반영 시점 맞춤
- 수수료 차감
= 비교 대상 금액
이것을 맞춘 뒤에 남는 차이만 보여줬다. 그러면 화면에 뭔가 뜨는 것 자체가 신호가 된다.
정상 차이를 안 걸러 내면 매일 안 맞는 화면이 되고 그 화면은 아무것도 알려 주지 않는다.
어느 쪽이 맞나
차이가 나면 어느 쪽을 믿을지 정해야 했다. PG 사가 정본인데 실제 돈이 오간 기록이기 때문이다.
그러면 우리 쪽이 틀린 것이고 왜 틀렸는지 찾아 고친다. 이 원칙을 먼저 정한 것이 중요했고 안 정하면 매번 어느 쪽이 맞나부터 논의한다.
다만 예외도 적었다. 상대 쪽 데이터가 명백히 이상한 경우는 확인 후 판단한다.
차이의 기록과 패턴
발견한 차이를 그냥 고치고 끝내지 않고 MySQL 의 별도 표에 기록했다.
날짜 / 건수 / 금액 / 원인 / 조치
몇 달 쌓인 것을 GROUP BY 해 보니 패턴이 보였다. 월말에 몰리는 것은 정산 주기 경계이고 특정 결제 수단에서 자주 나는 것은 그 연동에 문제가 있다는 뜻이며 어떤 원인은 반복되어 근본 수정 대상이 됐다.
한 건씩 고치는 것과 패턴을 보는 것은 다르다. 기록이 없으면 패턴이 안 보인다.
판단 기준 — 대조 로직과 허용 오차
만들고 보니 화면 자체는 단순했고 표 하나다. 일의 대부분은 대조 로직이었다.
어느 필드끼리 맞추나
시점을 어떻게 맞추나
무엇을 정상 차이로 볼 것인가
어디까지가 허용 오차인가
마지막이 특히 그랬다. 금액이 1원 다른 것도 차이로 잡을 것인가다.
반올림 때문에 생기는 1원은 잡아도 할 것이 없어서 HAVING 에 허용 오차를 뒀다. 다만 허용 오차 안이어도 건수는 세었는데 갑자기 늘면 그것도 신호이기 때문이다.
허용 오차를 두기 전에 볼 것이 하나 더 있다. 금액을 DOUBLE 같은 부동소수 컬럼에 담아 두면 합계 자체가 어긋나고 매뉴얼도 이 값들이 근사값이라 정확한 것처럼 비교하면 문제가 생긴다고 적고 있다. DECIMAL 로 담으면 그 자리에서 생기는 차이는 없어지고 ABS 로 두 합의 차만 재면 된다.
차이가 나면 자동으로 맞추는 기능을 넣을지도 고민했는데 안 넣었다. 돈과 관련된 값을 자동으로 고치면 잘못된 로직이 조용히 계속 고치고 아무도 모른다.
발견은 자동으로 하고 조치는 사람이 한다. 화면이 차이를 보여주고 사람이 확인하고 필요하면 정정하며 그 정정은 MySQL 이력에 남는다.
정리
- 두 시스템의 숫자 비교는 왜 다른지 먼저 세는 것부터다
- 시점과 취소 반영과 수수료는 정상 차이이고 누락만 문제다
- 정상 차이를 계산에 반영해야 화면이 신호가 된다
- 안 하면 매일 안 맞아서 아무도 안 본다
- 어느 쪽이 정본인지 먼저 정하고 안 정하면 매번 논의한다
- 차이를 기록하면 패턴이 보인다
- 일의 대부분은 화면이 아니라 대조 로직이다
- 허용 오차를 두되 그 안의 건수도 센다
- 금액은
DECIMAL에 담고DOUBLE이면 허용 오차 이전에 합계가 어긋난다 - 돈과 관련된 것은 발견은 자동으로 하고 조치는 사람이 한다